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((操作的成本是多少?他们的风格好吗?必要吗

谢谢。

C#中多个列表的并集

您正在寻找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>,您可以对其进行进一步筛选/处理。