Linq不同和最大:如何摆脱重复

时间:2019-03-01 21:15:48

标签: c# linq

我有以下列表:

var items = new List<Tuple<string, int, int>>()
            {
                 Tuple.Create("A", 3, 0),
                 Tuple.Create("A", 5, 0),
                 Tuple.Create("B", 1, 0),
                 Tuple.Create("C", 1, 0),
                 Tuple.Create("C", 3, 0),
                 Tuple.Create("C", 2, 0),
                 Tuple.Create("C", 3, 1)
            };

我有以下提示:

var results = (from item in items
                           group item by item.Item1 into groupedItems
                           let maxPriority = groupedItems.Max(item => item.Item2)
                           from element in groupedItems
                           where element.Item2 == maxPriority
                           select element).Distinct();

我得到这个:

Name    Priority
A       5
B       1
C       3
C       3

我只想区别如下:

Name    Priority
A       5
B       1
C       3

有人知道如何修改linq来做到这一点吗?先谢谢你。

注意:我知道Distinct具有允许您传递IComparer的重载。但是,如果可以在linq语句本身上更简单地完成操作,我想避免这种情况。我也不希望使用Distinct语句。

4 个答案:

答案 0 :(得分:1)

基本上,您要执行的操作是get the item from a sequence who has the max value for a particular selector function。因此,只需编写该函数(或使用其他人编写的函数)即可。请注意,在您的查询中,您要多次迭代序列以完成此操作,因此您可以做得更好。您只需执行一次即可实现该操作。

现在您要做的就是对分组的项目执行单个操作,您的查询将变得非常简单:

var query = items.GroupBy(item => item.Item1)
    .Select(group => group.MaxBy(item => item.Item2));

答案 1 :(得分:0)

好吧,您的查询包含项的所有属性,因此当我执行此操作时,结果实际上是

Item1  Item2  Item3
A      5      0
B      1      0
C      3      0
C      3      1

因此,您的Distinct呼叫实际上行为正确。我假设,由于您仅查看前两个属性,因此还应仅将它们包括在结果中。然后,非重复呼叫实际上会为您提供所需的结果:

var results = (from item in items
               group item by item.Item1 into groupedItems
               let maxPriority = groupedItems.Max(item => item.Item2)
               from element in groupedItems
               where element.Item2 == maxPriority
               select new {element.Item1, element.Item2}).Distinct();

请注意已替换的select new { ... }

更新:

然后,您的查询将类似于Matt的建议:

var results = (from item in items
               group item by item.Item1 into groupedItems
               let maxPriority = groupedItems.Max(item => item.Item2)
               from element in groupedItems
               where element.Item2 == maxPriority
               group element by new { element.Item1, element.Item2 } into
               groupByItem1Item2
               select groupByItem1Item2.OrderByDescending(element => element.Item3).First());

只需在.OrderByDescending(element => element.Item3)调用之前执行.First()

答案 2 :(得分:0)

在Item1,Item2上添加另一个分组,例如:

var results = (from item in items
                   group item by item.Item1 into groupedItems
                   let maxPriority = groupedItems.Max(item => item.Item2)
                   from element in groupedItems
                   where element.Item2 == maxPriority
                   group element by new { element.Item1, element.Item2 } into 
                   groupByItem1Item2
                   select groupByItem1Item2.First());

答案 3 :(得分:0)

这里是使用lambas且不添加任何第三方库的纯LINQ解决方案:

var results = items.GroupBy(item => item.Item1)
    .Select(grp => new {
        Group = grp,
        Item2Max = grp.Max(item => item.Item2)
    })
    .Select(x => new Tuple<string, int, int>(
        x.Group.Key,
        x.Item2Max,
        x.Group.Where(item => item.Item2 == x.Item2Max).Max(item => item.Item3)
    ));

这将输出:

Item1   Item2   Item3
A       5       0
B       1       0
C       3       1