Linq从其他列表中选择匹配列表

use*_*853 8 c# linq performance

我有这样的课

public class Category 
{
   CategoryID
   List<Product> ProductList
}
public class Product 
{
   CategoryID
}
Run Code Online (Sandbox Code Playgroud)

List<Category>大约15k排和List <Product>大约40k排.我正在使用这样的LINQ

CategoryList.ForEach(i =>
{
    i.ProductList = ProductList.Where(x => x.CategoryID == i.CategoryID).ToList();
});
Run Code Online (Sandbox Code Playgroud)

我想知道有任何实现更好的性能.在其他情况下,数据可能会增加或减少

Cod*_*aos 12

我认为使用并行性是愚蠢的,当对算法进行简单的更改可以将其加速千倍.假设CategoryID有一个体面GetHashCode()的字典/查找实现O(1)O(n)扫描列表的时间相比几乎具有查找时间.

两种可能的方法:

将类别转换为字典

假设类别具有唯一ID,您可以使用:

var categoryById = categories.ToDictionary(c => c.CategoryID);
foreach(var product in products)
{
    var category = categoryById[product.CategoryID];
    category.Products.Add(product);
}
Run Code Online (Sandbox Code Playgroud)

这有运行时O(products.Count + categories.Count)和使用O(categories.Count)内存.

如果类别不以空列表开头,则可能需要创建它.

将产品转变为Lookup

var productsByCategory = products.ToLookup(product => product.CategoryID);
foreach(var category in categories)
{
    category.Products = products[category.CategoryID].ToList();
}
Run Code Online (Sandbox Code Playgroud)

这有运行时O(products.Count + categories.Count)和使用O(products.Count)内存.

由于通常产品多于类别,因此这种方法需要更多内存.另一方面,查找可能无需在类别对象中嵌入产品列表.


Art*_*kov 5

您可以使用LINQ- PLINQ的并行实现.通常PLINQ会提高LINQ的速度,因为它可以更有效地使用所有可用内核.

CategoryList.AsParallel().ForAll(i =>
     {
         i.ProductList = ProductList.AsParallel.Where(x => x.CategoryID == i.CategoryID).ToList();
     });
Run Code Online (Sandbox Code Playgroud)

  • 当在O(n + m)中运行的小变化将导致性能提高数千倍时,并行化在O(n*m)中运行的低效代码是非常愚蠢的. (2认同)