【问题标题】:Create List by Unique Key with Linq使用 Linq 按唯一键创建列表
【发布时间】:2014-09-28 10:33:46
【问题描述】:

我有一个依赖类型的类:

class Dependency
{
    public int Source;
    public int Target:
}

给定List<Dependency> 的列表,我会得到以下列表(每一行都是源/目标对):

1, 2
1, 5
2, 1
3, 4
3, 6

是否可以将它们与 Linq 合并,​​以便生成以下内容 List<Tuple<int,List<int>>:

1, [2,5]
2, [1]
3, [4,6]

鉴于包含数千个项目的较大列表,使用 Linq 是执行上述合并的最快方法吗?

【问题讨论】:

  • SourceTarget 是单独的列表,还是具有 SourceTarget 属性的类?
  • 修改问题以包括类类型
  • Source 分组,其余的应该很容易。不过,不能谈论速度。

标签: c# linq


【解决方案1】:

您可以像这样使用 LINQ 分组运算符:

var items = new List<Dependency>();
// add your items to list

var result = (from i in items
             group i by i.Source
             into gr
             select new Tuple<int, List<int>>(gr.Key, gr.Select(a => a.Target).ToList())).ToList();

上述查询应该相当快,尽管很难与其他实现相同目标的方式进行比较。我建议在实践中进行测试 - 编写替代实现并比较性能。

【讨论】:

  • 如果您喜欢等效的方法:items.GroupBy(x=&gt;x.Source,(k,x)=&gt;new Tuple&lt;int,List&lt;int&gt;&gt;(k,x.Select(g=&gt;g.Target).ToList())).ToList();
【解决方案2】:

注意: This other answer 推荐 C# 的 group into 语法。我的回答显示了类似的东西,即.ToLookup(…) 运算符。如果您要问这两者之间的区别是什么,请参见例如以下问题:ILookup<TKey, TVal> vs. IGrouping<TKey, TVal>.

以下解决方案不会产生List&lt;Tuple&lt;int, List&lt;int&gt;&gt;&gt;,我不能说它是否是最快的解决方案,但它很可能是最简洁的:

ILookup<int,int> multiMap = dependencies.ToLookup(d => d.Source, d => d.Target);

.ToLookup(…) operatorSource 属性(由第一个 lambda 指定)将您的 dependencies 分组,而不是将完整的 Dependency 对象放入输出中,它只选择它们的 Target 值(如由第二个可选的 lambda 指定)。

你得到的是ILookup&lt;TKey,TElement&gt;,它本质上类似于Dictionary&lt;TKey,TValue&gt;,除了每个键可以有多个元素(值)。

这是一个示例,您可以如何迭代此类数据结构(所谓的multimap)中的所有值:

foreach (IGrouping<int,int> grouping in multiMap)  // enumerate over all groups
foreach (int target in grouping)  // enumerate over all values in one specific group
{
    int source = grouping.Key;  // get the key value of the group
    …
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多