C#中多个列表的并集
本文关键字:列表 | 更新日期: 2023-09-27 18:04:45
我正在为以下情况寻找一个优雅的解决方案:
我有一个类包含类似的列表
class MyClass{
...
public List<SomeOtherClass> SomeOtherClassList {get; set;}
...
}
第三个名为Model
的类包含一个List<Myclass>
,它是我从extern操作的类。
现在,我想用一个方法来扩展Model类,该方法在所有MyClass实例上返回所有唯一的SomeOtherClass实例。
我知道有Union()
方法,通过foreach循环,我可以很容易地解决这个问题,我确实做到了。然而,由于我是所有C#3+功能的新手,我很好奇,无论有没有Linq,如何才能更优雅地实现这一点。
我找到了一种方法,在我看来相当笨拙,但它很有效:
List<SomeOtherClass> ret = new List<SomeOtherClass>();
MyClassList.Select(b => b.SomeOtherClasses).ToList().ForEach(l => ret = ret.Union(l).ToList());
return ret;
注意:b.SomeotherClasses
属性返回一个List<SomeOtherClasses>
。
这段代码还远远不够完美,有些问题是因为我必须弄清楚什么是使用C#的好风格,什么不是。所以,我列出了一个关于这个片段的想法的小列表,我很高兴能得到一些评论。除此之外,我很高兴听到一些关于如何进一步改进此代码的评论。
- 临时列表
ret
可能是C#2中方法的一部分,但我应该能够使用方法链接来放弃这个列表,这正确吗?还是我没有抓住要点 - 是否真的需要使用中间
ToList()
方法?我只想对一个选择中的每个成员执行进一步的操作 - ToList((操作的成本是多少?他们的风格好吗?必要吗
谢谢。
您正在寻找SelectMany()
+Distinct()
:
List<SomeOtherClass> ret = MyClassList.SelectMany( x => x.SomeOtherClasses)
.Distinct()
.ToList();
SelectMany()
将"列表列表"扁平化为一个列表,然后您可以在该枚举中挑选不同的条目,而不是在各个子列表之间使用并集。
一般来说,你会想避免Linq的副作用,你最初的方法有点滥用这一点,我修改了ret
,这不是查询的一部分。
ToList()
是必需的,因为每个标准查询运算符都返回一个新的枚举,并且不会修改现有的枚举,因此您必须将最终的枚举结果转换回列表。ToList()
的成本是枚举的完整迭代,在大多数情况下,枚举是可以忽略不计的。当然,如果您的类可以使用IEnumerable<SomeOtherClass>
,那么您根本不必转换为列表。
您应该了解SelectMany。这样的东西应该会生成你的"平面"列表:
MyClassList.SelectMany(b => b.SomeOtherClasses)
它将返回一个IEnumerable<SomeOtherClass>
,您可以对其进行进一步筛选/处理。