【问题标题】:C# Expand Flat List<T> to Dictionary<T,ICollection<int>>C# 展开平面列表<T> 到 Dictionary<T,ICollection<int>>
【发布时间】:2012-05-10 04:01:17
【问题描述】:

我有一个List&lt;MyClass&gt;

public int MyClass
{
   public int One { get; set; }
   public int Two { get; set; }
}

现在,数据可以(并且确实)如下所示:

一:1,二:9

一:2,二:9

一:1,二:8

一:3,二:7

看看“一”是如何出现两次的?我想将这个平面序列投影到一个分组的Dictionary&lt;int,ICollection&lt;int&gt;&gt;

KeyValuePairOne: { Key: 1, Value: { 9, 8 }}

KeyValuePairTwo:{键:2,值:{9}}

KeyValuePairThree: { Key: 3, Value: { 7 }}

我猜我需要结合使用.GroupBy.ToDictionary

【问题讨论】:

  • 你的方向很好。你试过什么?
  • 是的,这正是我会做的
  • @Yorye - 我尝试了一个丑陋的循环,我知道这不是正确的方法,但不知道如何一起使用 .GroupBy.ToDictionary在这里,所以我来到堆栈寻求帮助。 :)
  • @RPM1984 您应该已经阅读了这些扩展方法并寻找一些示例。在不依赖响应的情况下从互联网学习是一项强大的技能。
  • @YoryeNathan - 同意。我知道如何单独使用每个,只是大脑冻结,我一生都无法弄清楚如何组合。

标签: c# linq dictionary


【解决方案1】:

这就是ToLookup 扩展方法的用途。如果键出现两次,ToDictionary 将抛出哪里,而 ToLookup 则可以使用它并执行您要查找的操作。

【讨论】:

  • ToLookup 很像做 GroupBy,单靠它不足以解决问题(用它制作字典)
  • @YoryeNathan 它比 GroupBy 更简洁:一个短语而不是两个。另外,你的答案正是——做一个GroupBy——很明显你认为它已经足够了(或者至少是最好的解决方案)。
  • GroupBy 是正确的,但添加了 ToDictionary。添加 ToDictionary 的 ToLookup 也可以。顺便说一句,它一点也不短。我要说的是,你仍然需要 ToDictionary,因为 OP 想要一本字典。
  • @YoryeNathan 够公平的。
  • 我收回“不是更短”的论点,因为我刚刚明白 OP 想要 Dictionary&lt;int, ICollection&lt;int&gt;&gt; 而不是 Dictionary&lt;int, MyClass&gt;,所以将值选择器传递给 LoopUp 确实会更简洁。但是,您通过不必要的查找来添加一些调用和委托。
【解决方案2】:
var list = new List<MyClass>();

var dictionary = list.GroupBy(x => x.One)
                     .ToDictionary(x => x.Key, x => x.ToArray());

【讨论】:

  • 正确,但它实际上是.ToDictionary&gt; 中的x =&gt; x.Select(y =&gt; y.Two).ToArray(),因为我想以Dictionary&lt;int,ICollection&lt;int&gt;&gt; 而不是Dictionary&lt;int,ICollection&lt;MyClass&gt;&gt; 结束
  • 我的错。但只要你有解决方案,我就很高兴。
【解决方案3】:

这正是你的做法:

Dictionary<int, List<MyClass>> result =
    items.GroupBy(x => x.One).ToDictionary(x => x.Key, x => x.ToList());

【讨论】:

  • 为什么不使用var?此外,.ToArray() 也会使 ICollection 变得更高效。仅当您打算在 ICollection 上使用“添加/删除”时,才应创建列表。
  • 这有点离题,但为什么要使用 var?具体的定义不是更可读更简洁吗?
  • @YoryeNathan:这里有三点。一:一个List也是一个ICollection;您的代码实际创建的是Dictionary&lt;int, MyClass[]&gt;。二:如果你没有使用var,你会注意到这一点。三:我测试了两者的 10,000 次迭代。列表:0.9582951 秒。数组:0.957012 秒。我认为这不重要。
  • 更新:这是在调试模式。在发布模式下,列表:1.13 秒,数组:1.56 秒。所以我宁愿使用List
  • @minitech 是的,我的代码会这样做,但您可以看到 OP 对我的回答的评论。我确实注意到这是我的代码正在做的事情,我只是没有注意问题中实际需要的结果。在我看来,使用 var 使代码更具可读性,最后 - 在测试数组与列表时,您还应该测试访问元素,如果您以一种至少需要 5 秒的方式执行此操作,我会更喜欢他们,以便更好地比较。众所周知,数组最适合访问元素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-30
  • 1970-01-01
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多