在C#.NET中将两个(或更多)列表合并为一个

zek*_*kia 219 .net c# list

是否可以使用C#在.NET中将两个或多个列表转换为一个列表?

例如,

public static List<Product> GetAllProducts(int categoryId){ .... }
.
.
.
var productCollection1 = GetAllProducts(CategoryId1);
var productCollection2 = GetAllProducts(CategoryId2);
var productCollection3 = GetAllProducts(CategoryId3);
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 408

您可以使用LINQ ConcatToList方法:

var allProducts = productCollection1.Concat(productCollection2)
                                    .Concat(productCollection3)
                                    .ToList();
Run Code Online (Sandbox Code Playgroud)

请注意,有更有效的方法可以做到这一点 - 上面将基本上遍历所有条目,创建一个动态大小的缓冲区.由于您可以预测开始的大小,因此您不需要此动态大小调整...因此您可以使用:

var allProducts = new List<Product>(productCollection1.Count +
                                    productCollection2.Count +
                                    productCollection3.Count);
allProducts.AddRange(productCollection1);
allProducts.AddRange(productCollection2);
allProducts.AddRange(productCollection3);
Run Code Online (Sandbox Code Playgroud)

(为了提高效率,这AddRange是特殊的ICollection<T>.)

除非你真的需要,否则我不会采用这种方法.

  • 我已经使用BenchmarksDotNet更新了gist(https://gist.github.com/mcliment/4690433)并进行了性能测试并进行了适当测试,`AddRange`是原始速度的最佳选择(大约4倍,列表越大)更好的增加),正如乔恩建议的那样. (13认同)
  • @MarcCliment:这是一个相当大胆的一揽子声明 - 特别是当`AddRange`从一个底层数组到另一个底层数组进行块复制时.你有证据的链接吗? (7认同)
  • @MarcCliment:哪个特例?哪个CLR?哪种CPU架构?在我的机器上,我得到了混合的结果.这就是为什么我不愿意陈述/接受诸如"BTW,`productionCollection1.ForEach(...)`之类的一致声明,而不是AddRange".很难很容易地描述性能.令我感到惊讶的是,AddRange并没有轻易打败它 - 我需要进一步调查. (5认同)
  • BTW,`productCollection1.ForEach(p => allProducts.Add(p))`比AddRange更高效. (4认同)
  • @MarcCliment:嗯,有一件事,在你的测试中,你不是*用正确的最终大小创建列表 - 而我的答案中的代码确实如此.这样做,至少使用AddRange进行10000*10000测试更快 - 尽管其他结果不一致.(你还应该在测试之间强制进行垃圾收集 - 我认为非常短的测试毫无意义.) (4认同)
  • @JonSkeet感谢您的建议.我更新了Gist,但在这种特殊情况下,ForEach略微优于AddRange. (2认同)

Ani*_*Ani 40

假设您想要一个包含指定类别ID的所有产品的列表,您可以将查询视为投影,然后进行展操作.有一个LINQ运算符可以做到:SelectMany.

// implicitly List<Product>
var products = new[] { CategoryId1, CategoryId2, CategoryId3 }
                     .SelectMany(id => GetAllProducts(id))
                     .ToList();
Run Code Online (Sandbox Code Playgroud)

在C#4中,您可以将SelectMany缩短为: .SelectMany(GetAllProducts)

如果您已经有代表每个Id的产品的列表,那么您需要的是连接,正如其他人指出的那样.

  • 如果OP由于任何其他原因不需要单个列表,这是一个很好的解决方案. (8认同)
  • 有一个类似的问题,即将放弃并发布一个问题,当我发现这一点.这是最好的答案.特别是如果代码已经在列表或数组中有这些类别,这在我的情况下是正确的. (2认同)

Bot*_*000 22

你可以使用LINQ组合它们:

  list = list1.Concat(list2).Concat(list3).ToList();
Run Code Online (Sandbox Code Playgroud)

List.AddRange()然而,更传统的使用方法可能更有效.


Stu*_*tLC 9

看看List.AddRange来合并列表


Dar*_*rov 7

您可以使用Concat扩展方法:

var result = productCollection1
    .Concat(productCollection2)
    .Concat(productCollection3)
    .ToList();
Run Code Online (Sandbox Code Playgroud)


dec*_*one 7

list4 = list1.Concat(list2).Concat(list3).ToList();
Run Code Online (Sandbox Code Playgroud)


sQu*_*r3l 7

我知道这是一个老问题,我想我可能只需要加 2 美分。

如果你有List<Something>[]你可以加入他们使用Aggregate

public List<TType> Concat<TType>(params List<TType>[] lists)
{
    var result = lists.Aggregate(new List<TType>(), (x, y) => x.Concat(y).ToList());

    return result;
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。

  • @qqtf 而不是 `list1.Concat(list2).Concat(list3)` 如果你有可变数量的列表怎么办?或列表&lt;List&lt;T&gt;&gt; (4认同)