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

本文关键字:两个 列表 何合并 合并 属性 | 更新日期: 2023-09-27 17:53:28

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

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中有更优雅的方法。

如果你有什么建议,请告诉我

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

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();

您可以在这里查看结果

试试这个:

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 Lists

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;
}

使用LINQ是正确的。

这里的答案都等同于给定的c#代码片段,除了这个代码片段非常低效并且会导致列表1。长度* list2。长度操作。

使用LINQ连接效率更高,结果大致为list1。长度+ list2。长度操作。

这是因为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<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);
    }
}