【问题标题】:List<T> Concatenation dynamicallyList<T> 动态连接
【发布时间】:2017-01-09 08:42:41
【问题描述】:

我正在尝试连接 List&lt;&gt; 如下-

 List<Student> finalList = new List<Student>();
 var sortedDict = dictOfList.OrderBy(k => k.Key);
 foreach (KeyValuePair<int, List<Student>> entry in sortedDict) {          
     List<Student> ListFromDict = (List<Student>)entry.Value;
     finalList.Concat(ListFromDict);
 }

但是没有发生串联。 finalList 保持为空。有什么帮助吗?

【问题讨论】:

    标签: c# dictionary concatenation generic-list


    【解决方案1】:

    Concat 的调用不会修改原始列表,而是返回一个新列表——或者完全准确地说:它返回一个IEnumerable&lt;string&gt;,它将生成两个列表的内容,而不修改其中任何一个.

    您可能想使用 AddRange 来满足您的需求:

    List<Student> ListFromDict = (List<Student>)entry.Value;
    finalList.AddRange(ListFromDict);
    

    甚至更短(一行代码):

    finalList.AddRange((List<Student>)entry.Value);
    


    因为entry.Value 已经是List&lt;Student&gt; 类型,所以你可以使用这个:

    finalList.AddRange(entry.Value);
    

    【讨论】:

    • 不需要演员表 - 鉴于它是 KeyValuePair&lt;int, List&lt;Student&gt;&gt;Value 的类型已经是 List&lt;Student&gt;。 (OP 的原始代码中的演员也是多余的。)
    • 是的,我没有首先关注类型,但我在您回复时看到了它。它现在在里面。
    • 附加提示:Concat 是一种 LINQ 扩展方法,所有这些方法都使用 List&lt;T&gt; 作为数据源,但不要更改原始集合。提到的AddRange 是一个普通的List&lt;T&gt; 方法,例如AddRemove,因此会改变集合。
    【解决方案2】:

    其他答案已经解释了为什么 Concat 没有帮助您 - 但它们都保留了您的原始循环。没有必要 - LINQ 已为您提供:

    List<Student> finalList = dictOfList.OrderBy(k => k.Key)
                                        .SelectMany(pair => pair.Value)
                                        .ToList();
    

    需要明确的是,这会替换整个现有代码,而不仅仅是循环体。

    简单得多 :) 每当您发现自己使用 foreach 循环,它除了构建另一个集合之外什么都不做,看看您是否可以使用 LINQ 消除该循环是值得的。

    【讨论】:

      【解决方案3】:

      您可能需要阅读Enumerable.Concat 上的文档:

      返回值
      类型:System.Collections.Generic.IEnumerable
      一个 IEnumerable,包含两个输入序列的连接元素。

      因此您可能希望使用包含新元素的返回值。

      作为替代方案,您可以使用List.AddRange,它将指定集合的​​元素添加到列表的末尾

      顺便说一句,您还可以通过简单的 LINQ 查询来实现您的目标:

      var finalList = dictOfList.OrderBy(k => k.Key)
                                .SelectMany(k => k.Value)
                                .ToList();
      

      【讨论】:

      • @downvoter 想详细说明一下,以便我可以修正我的答案?
      【解决方案4】:

      正如here 指定的那样,Concat 生成一个新序列,而AddRange 实际上将元素添加到列表中。因此,您应该将其重写为:

      List<Student> finalList = new List<Student>();
      var sortedDict = dictOfList.OrderBy(k => k.Key);
      foreach (KeyValuePair<int, List<Student>> entry in sortedDict) {          
          List<Student> ListFromDict = (List<Student>)entry.Value;
          finalList.AddRange(ListFromDict);
      }
      

      此外,由于entry.Value 已经是List&lt;T&gt;(技术上只需要是IEnumerable&lt;T&gt;),因此您可以通过省略对List&lt;T&gt; 对象的强制转换来提高效率:

      var sortedDict = dictOfList.OrderBy(k => k.Key);
      foreach (KeyValuePair<int, List<Student>> entry in sortedDict) {
          finalList.AddRange(entry.Value);
      }
      

      【讨论】:

        【解决方案5】:

        Concat 方法不会修改原始集合,而是返回带有连接结果的全新集合。所以,要么尝试finalList = finalList.Concat(ListFromDict),要么使用修改目标列表的AddRange方法。

        【讨论】:

        • 那一定是finalList = finalList.Concat(ListFromDict).ToList(),因为Concat返回一个源类型的IEnumerable,所以不能直接赋值给列表。
        猜你喜欢
        • 1970-01-01
        • 2019-11-21
        • 1970-01-01
        • 2021-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多