如何合并给定属性上的两个列表

我有两个查询,每个查询返回一个对象列表。

List list1 = (....query...) List list2 = (....query...) 

“A”是对象模型。

两个查询都返回几乎相同的对象,但设置了不同的属性。

我想删除重复项,根据对象A的属性将它们合并到一个列表中。

基本上是这样的:

 List finalLis = list1 join list2 on elemList1.somePropID == elemList2.somePropID 

在简单的C#样式中,它将是这样的:

 foreach(elem1 : list1) { foreach(elem2: list1) { if(elem1.someID == elem2.someID) { elem1.someProp = elem2.someProp elem1.otherProp = elem2.otherProp } } } 

我不想这样做,因为我确信在linq中有更优雅的方式。

如果您有任何建议,请让我知道。

Linq可以帮助您选择但不能更新。 所以你不会摆脱foreach声明。 所以你的任务可以用linq编写,如下所示:

 //the query is like LEFT JOIN in SQL var query = from x in list1 join y in list2 on x.IDItem equals y.IDItem into z from q in z.DefaultIfEmpty() select new {IOne = x, ITwo = q}; foreach (var pair in query) { if (pair.ITwo != null) // && pair.IOne.OneProperty != null pair.IOne.OneProperty = pair.ITwo.TwoProperty; } var resultList = query.Select(x => x.IOne).ToList(); 

您可以在此处查看结果。

想要使用LINQ是正确的。

这里的答案都等同于给定的C#片段,除了该片段效率非常低并且将导致list1.Length * list2.Length操作。

使用LINQ连接更有效,并导致大致list1.Length + list2.Length操作。

这是因为id上的连接将使用字典执行类似的操作

 // create a dict so that you can lookup things in item1 based on id var list1IdToADict = list1.ToDictionary(a => a.id); //filter out things not in both lists (join on there id) var joinedList2 = list2.Where(a => list1IdToADict.ContainsKey(a.id)); 

其他答案更加精致,但如果你想这样做,你可以完成

 foreach(var a in joinedList2){ a.someProp = list1IdToADict[a.id].someProp; a.otherProp = list1IdToADict[a.id].otherProp; } 

List任何解决方案都将在N * Log(n)处执行,因为列表需要进行排序。

在模型上实现相等成员并使用HashSet

这在复杂性和分配方面都是最佳的。

 var set1 = new HashSet { new Model(0, "000"), new Model(2, "222"), new Model(4, "444"), }; var set2 = new HashSet { new Model(1, "111"), new Model(2, "2222"), new Model(3, "333"), }; set1.ExceptWith(set2); set1.UnionWith(set2); 

要添加,使用覆盖集作为结果集会更快。

 set2.UnionWith(set1); 

上述样本中的类Model

 class Model { public readonly int Id; public string Data; public Model(int id, string data) { Id = id; Data = data; } public override int GetHashCode() { return Id; } protected bool Equals(Model other) { return Id == other.Id; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; return obj.GetType() == GetType() && Equals((Model) obj); } }