繁体   English   中英

根据属性将两个列表合并为一个

[英]Combine two lists into one based on property

我想问一下,是否有一种优雅而有效的方法将两个MyClass列表合并为一个?

MyClass看起来像这样:

  • ID: int
  • 名称: string
  • ExtID: int?

并且列表从不同的源填充,列表中的对象共享ID,所以它看起来像这样:

MyClass instance from List1
ID = someInt
Name = someString
ExtID = null

来自List2的MyClass实例

ID = someInt (same as List1)
Name = someString (same as List1)
ExtID = someInt

我基本上需要的是将这两个列表组合在一起,因此结果是一个包含以下内容的列表:

ID = someInt (from List1)
Name = someString (from List1)
ExtID = someInt (null if no corresponding item - based on ID - on List2)

我知道我可以简单地使用foreach循环来做这个,但是我想知道是否有更优雅和可能更喜欢(由于性能,可读性)方法?

这是你想要的吗

var joined = from Item1 in list1
         join Item2 in list2
         on Item1.Id equals Item2.Id // join on some property
         select new MyClass(Item1.Id, Item1.Name, Item1.ExtID??Item2.ExtID);

编辑:如果您正在寻找外部联接,

var query = from Item1 in list1
            join Item2 in list2 on Item1.Id equals Item2.Id into gj
            from sublist2 in gj.DefaultIfEmpty()
            select new MyClass(Item1.Id, Item1.Name, sublist2??string.empty);

可读性明智,使用foreach循环并不是一个太糟糕的主意。

有很多方法取决于优先级,例如。 联盟+查询:

//this will create a key value pairs: id -> matching instances
var idMap = list1.Union(list2).ToLookup(myClass => myClass.ID);
//now just select for each ID the instance you want, ex. with some value
var mergedInstances = idMap.Select(row => 
      row.FirstOrDefault(myClass => myClass.ExtId.HasValue) ?? row.First());

上面的好处是它可以处理任何数量的任何列表,即使它们包含许多重复的isntances,然后你可以很容易地修改合并的条件

一个小的改进是提取合并实例的方法:

MyClass MergeInstances(IEnumerable<MyClass> instances){
     return instances.FirstOrDefault(myClass => myClass.ExtId.HasValue) 
          ?? instances.First(); //or whatever else you imagine
}

现在只需在上面的代码中使用它

 var mergedInstances = idMap.Select(MergeInstances);

清洁,灵活,简单,无附加条件。 表现明智不完美,但谁在意。

编辑:因为性能是优先级,还有一些选项

  1. 像上面那样进行查找,但仅针对较小的列表。 然后迭代更大的并执行所需的更改O(m log m)+ O(n)。 m - 较小的列表大小,n-较大的列表大小 - 应该是最快的。

  2. 按元素ID排序两个列表。 创建一个for循环,迭代两个循环,保持当前索引到两个列表具有相同id的元素。 将索引移动到两个列表中找到的下一个最小ID,如果只有一个,则仅将其移动。 O(n log n)+ O(m log m)+ O(n);

我想在该类的方法中创建foreach循环,所以每当你需要做这样的事情你就会使用像

instanceList1.MergeLists(instanceList2)

使用此方法,您可以使用合并操作控制所需的一切。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM