从一个列表中选择仅存在于另一个列表中的列表并按第二列表排序 - linq

时间:2016-10-22 18:15:27

标签: c# linq c#-4.0

我有两个阵列..

var data1 = new[] { 
        new { Product = "Product 1", Year = 2009, Sales = 1212 },
        new { Product = "Product 2", Year = 2009, Sales = 522 },
        new { Product = "Product 1", Year = 2010, Sales = 1337 },
        new { Product = "Product 2", Year = 2011, Sales = 711 },
        new { Product = "Product 2", Year = 2012, Sales = 2245 },
        new { Product = "Product 3", Year = 2012, Sales = 1000 }
    };

var data2 = new[] { 
        new { Product = "Product 1", Year = 2009, Sales = 1212 },
        new { Product = "Product 1", Year = 2010, Sales = 1337 },
        new { Product = "Product 2", Year = 2011, Sales = 711 },
        new { Product = "Product 2", Year = 2012, Sales = 2245 }
    };

我希望按data1Product进行分组,并按Salesdata2中存在的那些产品进行分组,并按相同方式排序因为他们在data2。请注意,即使data2中存在某个产品,data1data2中的所有年份都不会出现在{ Product = "Product 2", Year = 2009, Sales = 522 }中(例如data1),因此分组并且总和必须在data1.GroupBy(x=>x.Product) .Select(x=>new {Product=x.Key,Total= x.Sum(s=>s.Sales)}) 上发生。

要进行分组并总结以下应该有效..

Product

但我如何确保我只选择data2中的产品并按{{1}}排序结果,如data2

3 个答案:

答案 0 :(得分:1)

您需要做两件事:首先,您从data2中选择可用的产品。为此,您可以使用Select的重载,它也会给出匹配元素的索引。

其次,您根据data1中的产品过滤了data2,然后执行分组。最后一步,添加一个与CorrespondingIndex中产品索引相匹配的新属性data2。此索引可用于根据data1中产品的排序对您的data2列表进行排序。

  var productsWithIndex = data2
    .Select(x => x.Product)
    .Distinct()
    .Select((p, idx) => new {Product = p, Index = idx});

  var filteredProducts = data1
    .Where(x => productsWithIndex.Select(p => p.Product).Contains(x.Product))
    .GroupBy(x => x.Product)
    .Select(x => new
    {
      Product = x.Key,
      Total = x.Sum(s => s.Sales),
      CorrespondingIndex = productsWithIndex.Single(p => p.Product == x.Key).Index
    })
    .OrderBy(x => x.CorrespondingIndex);

答案 1 :(得分:1)

我会采取不同的方法。

由于您希望最终结果以相同的顺序包含第二个列表中的产品,因此我首先从第二个列表中获取Distinct个产品。

虽然文档中没有明确说明,但Distinct方法(类似于GroupBy)按照源中唯一元素第一次出现的顺序生成不同的元素,因此结果为Distinct将是正确顺序的最终结果的产品。

然后我会使用GroupJoin将它与第一个列表相关联,最后得到一个非常有效的查询:

var result = data2.Select(item => item.Product).Distinct()
    .GroupJoin(data1, product => product, item => item.Product, (product, group) =>
        new { Product = product, Sales = group.Sum(item => item.Sales) })
    .ToList();

答案 2 :(得分:0)

如果用户1384848去了,你甚至不需要详细介绍。 你可能会得到更简单的东西:

var result =
                data1.Where(e => data2.Any(x => x.Product == e.Product))
                    .GroupBy(arg => arg.Product,
                        (name, products) => new {Product = name, Total = products.Sum(e => e.Sales)})
                    .OrderBy(d => d.Product);