我有两个查询,每个查询返回一个对象列表。
List<A> list1 = (....query...)
List<A> list2 = (....query...)
“A”是对象模型。
两个查询都返回几乎相同的对象,但设置了不同的属性。
我想删除重复项,根据对象A的属性将它们合并到一个列表中。
基本上是这样的:
List<A> 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中有更优雅的方式。
如果您有任何建议,请告诉我。
答案 0 :(得分:1)
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();
您可以查看结果here。
答案 1 :(得分:0)
试试这个:
List<A> list = (from e1 in list1
join e2 in list2
on e1.ID equals e2.ID
select new A
{
ID = l2.ID,
someProp1 = l2.someProp1,
someProp2 = l2.someProp2
}).ToList();
然后你会得到一个包含所有元素的第三个列表。
此链接可能有所帮助:LINQ Join 2 List<T>s
答案 2 :(得分:0)
Linq用于查询,而非更新。您可以简化连接,但仍需要循环执行更新。
类似的东西:
List<A> finalList =
from item1 in list1
join item2 in list2 on item1.somePropID equals item2.somePropID
select new{Item1 = item1, Item2 = item2};
foreach(var item in finalList)
{
item.Item2.someProp1 = item.Item1.someProp1;
item.Item2.someProp2 = item.Item1.someProp2;
}
答案 3 :(得分:0)
想要使用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;
}
答案 4 :(得分:0)
List<T>
以上的任何解决方案最多都会在N * Log(n)处执行,因为需要对列表进行排序。
在您的模型上实施平等成员,并改为使用HashSet<T>
。
这在复杂性和分配方面都是最佳的。
var set1 = new HashSet<Model>
{
new Model(0, "000"),
new Model(2, "222"),
new Model(4, "444"),
};
var set2 = new HashSet<Model>
{
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);
}
}