【问题标题】:LINQ aggregating multiple IEnumerables into one?LINQ将多个IEnumerables聚合为一个?
【发布时间】:2011-09-24 10:46:40
【问题描述】:

我有一个定义为<int, IEnumerable<char>> 的字典。假设数据填充如下:

1, a b c d e
2, f g h i j
3, k l m n o

如果我有一个由 1 和 3 组成的 IEnumerable,那么 LINQ 返回 'a b c d e k l m n o' 会是什么样子(假设空格代表一个迭代)。

【问题讨论】:

  • 你能把它作为答案发布吗?与 SelectMany 相关的任何内容都可能很有趣,因为该功能令人困惑:)
  • 备忘单:Select = "map", SelectMany = "flatmap", Where = "filter", Concat = "append" -- 这就是我使用的在我自己的脑海里;-)
  • @Michael:根据我的经验,不熟悉 SelectMany 的开发人员在使用理解语法的“compound from”时会更容易——例如,在 msdn.microsoft.com/en-us/vcsharp/aa336758 的 SelectMany 示例中

标签: c# linq


【解决方案1】:

SelectMany 确实是您想要的,但恕我直言,使用理解语法并让它为您进行映射更具可读性,因此类似于:

var dict = ... // dictionary
var keys = ... // enumerable with 1 and 3 in it
var result = from key in keys
             from val in dict[key]
             select val;

如果/需要的话,也更容易(再次恕我直言)在那里扔一个“orderby”。

当然,如果您发现扩展方法版本更易于阅读/解析,那么请务必使用它。 :)

【讨论】:

    【解决方案2】:

    如果找不到密钥,则需要 KeyNotFoundException:

    IEnumerable<char> result = keys.SelectMany(key => d[key]);
    

    如果您想静默忽略未找到的键:

    IEnumerable<char> result = keys.Where(key => d.ContainsKey(key))
                                   .SelectMany(key => d[key]);
    

    【讨论】:

      【解决方案3】:

      假设你有

      var someEnumerables = new Dictionary<int, IEnumerable<char>>();
      

      然后

      // Flattened will be an enumeration of the values ordered first by the key
      var flattened = someEnumerables.OrderBy(kvp => kvp.Key).SelectMany(kvp => kvp.Value)
      

      【讨论】:

      • +0;正确显示了 SelectMany 的使用,但没有解决 OP 按键列表过滤的要求。
      【解决方案4】:

      正如您在评论中提到的,您可以使用SelectManyIEnumerables 中的IEnumerable 聚合成一个IEnumerable。但是,您也可以使用 Concat 将两个单独的集合组合成一个选择(或者您可以将其链接起来以组合任意多个)。

      【讨论】:

        【解决方案5】:

        您需要一个 Where 子句来过滤字典中包含的键,并需要一个 SelectMany 子句来从字典中包含的每个列表中获取单个可枚举列表。

        Dictionary<int, IEnumerable<char>> dict; // contains all of your key-value pairs
        IEnumerable<int> keys; // contains the keys you want to filter by
        
        IEnumerable<char> data = dict.Where(kvp => keys.Contains(kvp.Key))
                                     .SelectMany(kvp => kvp.Value);
        
        // or, alternatively:
        
        IEnumerable<char> data = keys.SelectMany(i => dict[i]);
        

        请注意,如果您的字典中不存在 keys 枚举中的键,则第二个查询将引发异常。

        【讨论】:

        • 你真的应该建立在 keys 集合的基础上,而不是遍历字典中的所有项目。
        • 你是对的;我添加了一种更简洁的方法,并附有免责声明。
        【解决方案6】:

        不清楚您是只想要 1 和 3 行还是全部(1、2 和 3)。这是两者的解决方案

        Dictionary<int, string> map = ...;
        // 1 and 3 only
        IEnumerable<char> result1 = map
          .Where(x => x.Key == 1 || x.Key == 3)
          .OrderyBy(x => x.Key)
          .SelectMany(x => x.Value)
        
        // All
        IEnumerable<char> result2 = map
          .OrderyBy(x => x.Key)
          .SelectMany(x => x.Value)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-01
          • 1970-01-01
          • 2020-02-04
          • 2010-09-14
          • 1970-01-01
          相关资源
          最近更新 更多