LINQ - 选择每组最大属性值的记录

时间:2017-05-05 12:25:01

标签: c# .net linq group-by

我有这样的数据集:

GroupName   GroupValue   MemberName   MemberValue
'Group1'    1            'Member1'    1
'Group1'    1            'Member2'    2
'Group2'    2            'Member3'    3
'Group2'    2            'Member4'    2
'Group3'    2            'Member5'    4
'Group3'    2            'Member6'    1

我想要选择的是每个MemberValue最多GroupName的行,但仅适用于那些GroupName最大的GroupValue行,并通过它们进入委托功能。像这样:

'Group2'    2            'Member3'    3
'Group3'    2            'Member5'    4

到目前为止,我已尝试过这种格式......

data.Where(maxGroupValue => 
    maxGroupValue.GroupValue == data.Max(groupValue => groupValue.GroupValue))
.Select(FunctionThatTakesData)

...但这只是给了我Group2和Group3的每个成员。我已尝试在GroupBy()之前加Select(),但这会将输出转换为IGrouping<string, DataType>,因此FunctionThatTakesData()不知道如何处理它,我无法再做Where()来过滤掉最多MemberValue次。

如何才能正确过滤并传递给我的函数?

2 个答案:

答案 0 :(得分:6)

您可以使用以下Linq执行此操作。

var results = data.GroupBy(r = r.GroupValue)
    .OrderByDescending(g => g.Key)
    .FirstOrDefault()
    ?.GroupBy(r => r.GroupName)
    .Select(g => g.OrderByDescending(r => r.MemberValue).First());

首先,您必须对GroupValue进行分组,然后按KeyGroupValue)降序排列组,然后选择第一个。现在,您拥有最大GroupValue的所有行。然后,您对GroupName上的内容进行分组,然后从这些组中按降序排列MemberValue,并使用First行获取每个GroupName组中的行,其中包含最大值MemberValue {1}}。此外,我?.之后使用C#6空条件运算符FirstOrDefault,以防data为空。如果您不使用C#6,那么您需要预先处理该案例,而只需使用First

答案 1 :(得分:0)

基本上你想要的是将你的数据元素分成具有GroupName相同值的组。从您想要获取一个元素的每个组中,即属性MemberValue具有最大值的元素。

每当您有一系列项目,并且您希望根据您使用的序列中项目的一个或多个属性的值将此序列划分为组Enumerable.GroupBy

'GroupBy'将您的序列作为输入和一个额外的输入参数:一个函数,用于选择要在您决定在哪个组中显示项目时要比较的项目属性。

在您的情况下,您希望将序列分成组,其中组中的所有元素具有相同的GroupName

var groups = mySequence.GroupBy(element => element.GroupName);

它做什么,它从mySequence中的每个元素获取属性GroupName,并将此元素放入一组具有此GroupName值的元素。

使用您的示例数据,您将拥有三个组:

  • 包含GroupName ==“Group1”的所有元素的组。序列的前两个元素将在此组中
  • 包含GroupName ==“Group2”的所有元素的组。序列的第三和第四个元素将在此组中
  • 具有GroupName ==“Group3”的所有元素的组。序列的最后两个元素将在此组中

每个组都有一个属性Key,包含您的选择值。此密钥标识该组,并保证在您的组集合中是唯一的。因此,您将拥有一个包含Key ==“Group1”的组,一个包含Key ==“Group2”的组等。

除了Key之外,每个组都是组中元素的序列(注意:组 IS 是一个可枚举的序列,而不是: HAS 一个可枚举的序列。

您的第二步是从每个组中获取组中具有MemberValue最大值的元素。为此,您可以按属性MemberValue的降序值对组中的元素进行排序,然后选择第一个元素。

var myResult = mySequence.GroupBy(element => element.GroupName)
    // intermediate result: groups where all elements have the same GroupName
    .Select(group => group.OrderByDescending(groupElement => groupElement.MemberValue)
    // intermediate result: groups where all elements are ordered in descending memberValue
    .First();

结果:从降序的memberValue排序的每个组中,取第一个元素,该元素应该是最大的元素。

如果您只想要memberValue值最大的元素,那么订购完整的组效率不高。可以找到答案 here on StackOverflow