C# 添加列表<&燃气轮机;转到另一个列表<&燃气轮机;通过过滤
我有一个模型课:C# 添加列表<&燃气轮机;转到另一个列表<&燃气轮机;通过过滤,c#,.net,list,C#,.net,List,我有一个模型课: public class Person { public int Id { get; set; } public string Name { get; set; } } 当我添加两个列表时: List<Person> people1 = new List<Person> { new Person() { Id = 1, Name = "Name1" }, new Person() { Id = 2, Name = "N
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
当我添加两个列表时:
List<Person> people1 = new List<Person> {
new Person() { Id = 1, Name = "Name1" },
new Person() { Id = 2, Name = "Name2" },
new Person() { Id = 3, Name = "Name3" },
};
List<Person> people2 = new List<Person> {
new Person() { Id = 1, Name = "Name1" },
new Person() { Id = 4, Name = "Name4" },
new Person() { Id = 5, Name = "Name5" },
};
people1.AddRange(people2);
List people1=新列表{
new Person(){Id=1,Name=“Name1”},
newperson(){Id=2,Name=“Name2”},
new Person(){Id=3,Name=“Name3”},
};
列表人2=新列表{
new Person(){Id=1,Name=“Name1”},
newperson(){Id=4,Name=“Name4”},
newperson(){Id=5,Name=“Name5”},
};
people1.AddRange(people2);
如果people2
中的person
在people1
中具有相同的id
。我如何才能做到这一点?您可以很容易地使用LINQ实现这一点,但效率低下:
people1.AddRange(people2.Where(p2=>!people1.Any(p1=>p1.Id==p2.Id));
或者您可以先创建一组ID:
HashSet-people1id=newhashset(people1.Select(p1=>p1.Id));
people1.AddRange(people2.Where(p2=>!people1id.Contains(p2.id));
第一种方法显然更简单,但如果列表变大,它可能会变慢,因为对于people2
中的每个元素,它将查看people1
中的每个元素
如果people1
很大,则第二种方法的速度会明显加快。如果people2
很大,则您不会得到太多好处。例如,如果people1
只包含几个人,则在哈希集中查找ID不会比在列表中查找快多少
不过,你可以采取完全不同的方法。如果你让你的Person
类型基于ID实现IEquatable
,或者创建一个这样做的IEqualityComparer
,如果你不太需要修改现有列表,那么你就需要“两个列表的联合”,如果您不关心顺序,并且如果每个列表中的所有条目都是唯一的,或者您不介意删除重复项,则可以使用:
//如果需要,请将比较器指定为另一个参数。
//如果需要列表,可以调用ToList查看结果。
var union=people1.union(people2);
(该解决方案有很多条件,但它们很可能都是有效的。)您可以将运算符用于自定义IEqualityComparer
。这将创建一个新列表,它是其他2个条件的组合。实现customer IEqualityComparer可以让您控制构成相同记录的内容
var allPeople = people1.Union(people2, new PersonComparer());
public class PersonComparer : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
// ommited null checks etc
return x.Id == y.Id;
}
public int GetHashCode(Person obj)
{
// ommited null checks etc
obj.Id.GetHashCode()
}
}
var allPeople=people1.Union(people2,newpersoncomparer());
公共类人员比较:IEqualityComparer
{
公共布尔等于(人x,人y)
{
//ommited空检查等
返回x.Id==y.Id;
}
public int GetHashCode(Person obj)
{
//ommited空检查等
obj.Id.GetHashCode()
}
}
使用以下方法:
people1.AddRange(people2.Except(people1));
但首先需要在Person类中重写Equal和GetHashCode:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public override bool Equals(object obj)
{
if (!(obj is Person))
return false;
Person p = (Person)obj;
return (p.Id == Id && p.Name == Name);
}
public override int GetHashCode()
{
return String.Format("{0}|{1}", Id, Name).GetHashCode();
}
}
或者,您可以使用自定义相等比较器,然后使用Distinct(new distinctiontemcomparer())
:
如果只需要根据Id
进行区分,则可以从这两种方法中排除名称
基于,第二种方法似乎更好,因为Microsoft已经建议不要在引用类型上重载运算符equals。我认为最好的解决方案是使用LINQ。编写的代码非常简单和简短:
people1.AddRange(people2.Where(x => !people1.Any(y => x.Id == y.Id)));
你有没有想过改用
字典
您可以将Id
用作键
,并且它不允许存在重复的键
以下代码是我以前使用过的一种方式:
var dictionary = people1.ToDictionary(x => x.Id, x => x);
foreach(var person in people2)
{
if(!dictionary.ContainsKey(item.Id))
{
dictionary.Add(item.Id, item);
}
}
也许有更好的方法,但这对我来说很有效
这样,当您向字典中添加项目时,它将不允许您添加具有相同Id
的内容
也检查<代码> HasStuts,因为它们做了类似的事情。
所以,你认为两个实例的人是基于ID的相同的吗?如果<代码>名称< /代码>属性不同,应该发生什么?应该保存在Pube中的那个还是应该被另一个替换?事实上,这是不可能的,因为我是ReTeRe。我从数据库中获取了这些数据。但如果你将此可能性作为一个答案,也许你可以帮助其他人。因为它不能解决你的问题,我希望有人(最好是公认的答案)将其包含在他们的问题中。我怀疑OP是否从我对问题的评论中考虑了这种情况。(如果两个人
具有相同的Id
但不同的姓名
?)+1对于添加2个解决方案,不确定第二个是否有效,但它很容易阅读和测试。@Glenvanacker:如果人1
很大,第二个应该比第一个好得多。@Fildor:我假设OP问了他们想问的问题。@JonSkeet公平,这只是一个想法。但这似乎很重要无论如何都是可能的。所以不用担心。更好的方法是使用dictionary[item.ID]=item。除非它更喜欢来自内部集合的数据,以防重复。这不会起作用。Union直接使用哈希代码进行比较。因此,仅实现Equals不会起作用。您需要添加一个适当的GetHashCode(Person obj)
实现该功能。@RobinB correct-为了简洁起见,我从上面推荐了空检查、GetHashCode等。为了清晰起见,将进行更新。谢谢。我认为这可能是一个很大的陷阱,让人们稍后看到这一点,只需返回obj.GetHashCode()
,然后问自己为什么他们的等于()
永远不会执行。
people1.AddRange(people2.Where(x => !people1.Any(y => x.Id == y.Id)));
var dictionary = people1.ToDictionary(x => x.Id, x => x);
foreach(var person in people2)
{
if(!dictionary.ContainsKey(item.Id))
{
dictionary.Add(item.Id, item);
}
}