根据属性将两个列表合并为一个列表(Combine two lists into one based on property)

编程入门 行业动态 更新时间:2024-10-16 02:25:00
根据属性将两个列表合并为一个列表(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循环来做到这一点,但我很想知道是否有更优雅或者更可取的方法(由于性能和可读性)?

I would like to ask whether there's an elegant and efficient way to merge two lists of MyClass into one?

MyClass looks like this:

ID: int Name: string ExtID: int?

and the lists are populated from different sources and objects in lists do share ID, so it looks like that:

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

And MyClass instance from List2

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

What I basically need is to combine these two lists, so the outcome is a list containing:

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

I know I can do this simply using foreach loop, but I'd love to know if there's more elegant and maybe preferred (due to performance, readability) method?

最满意答案

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

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

上面的好处是它可以处理任何数量的任何列表,即使它们包含许多重复的事件,然后您可以轻松地修改合并条件

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

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

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

var mergedInstances = idMap.Select(MergeInstances);

清洁,灵活,简单,没有附加条件。 性能不明智,但谁在乎。

编辑:因为表现是优先考虑的,所以还有更多的选择

做一个类似上面的查找,但仅限于较小的列表。 然后遍历更大的并做所需的更改O(m log m)+ O(n)。 m - 更小的列表大小,n更大的列表大小 - 应该是最快的。

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

There are many approaches depending on what is the priority, ex. Union + Lookup:

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

The benefit of above is that it will work with whatever amount of whatever lists even if they contain many duplicated isntances and then you can easily modify the conditions of merging

A small improvement would be to extract a method to merge instances:

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

and now just use it in the code above

var mergedInstances = idMap.Select(MergeInstances);

Clean, flexible, simple, no additional conditions. Performance wise not perfect, but who cares.

Edit: since performance is the priority, some more options

Do a lookup like above but only for the smaller list. Then iterate through the bigger and do the needed changes O(m log m) + O(n). m - smaller list size, n- bigger list size - should be fastest.

Order both lists by elements ids. Create a for loop, that iterates through both of them keeping current index to the element with same id for both lists. Move index to the next smallest id found in both list, if one has it only, move only this on. O(n log n) + O(m log m) + O(n);

更多推荐

本文发布于:2023-08-06 00:52:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1442449.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:列表   并为   属性   两个   property

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!