2017-05-05 21 views
1

あたり最大プロパティ値を持つレコードを選択:LINQ - 私はこのようなデータセットを持っているグループ

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 

私は何を選択することGroupNameあたりの最大MemberValueを持つ行であるが、唯一のそれらのためGroupNameが最大のGroupValueを持ち、それらをデリゲート関数に渡します。このように:

'Group2' 2   'Member3' 3 
'Group3' 2   'Member5' 4 
私はこのフォーマットを試してみたこれまでのところ

...

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

...しかし、それはちょうど私のグループ2とグループ3のすべてのメンバーを示します。私はSelect()の前にGroupBy()を置こうとしましたが、出力がIGrouping<string, DataType>に変わるので、FunctionThatTakesData()は何をするのか分からず、別のWhere()を実行して最大MemberValueをフィルタリングできません。

このデータセットを適切にフィルタリングして機能に渡すにはどうすればよいですか?

答えて

3

これは、次の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上のグループに持って、その後(GroupValueである)Keyの降順でグループを注文すると、最初の1を取ります。これで、すべての行が最大GroupValueになりました。次に、GroupNameのグループをグループ化し、それらのグループから降順でMemberValueを注文し、の行を使用して、MemberValueの各GroupNameグループの行を取得します。また、dataが空の場合、FirstOrDefaultの後にC#6ヌル条件演算子?.を使用しています。 C#6を使用していない場合は、そのケースをフロントで処理する必要があります。代わりにFirstを使用してください。

+0

ありがとう見つけることができます!今、各グループに同じ値を持つ複数のメンバーがあるとしましょう... 'First()'の代わりに 'Where()'を使うべきですか?その場合 – JAF

+1

あなたは '.SelectMany(グラム=> g.GroupBy(R => r.MemberValue).OrderByDescending(SG => sg.Key)1次回は())'最後の行を交換したいと思います。 – juharr

+0

Genius!ありがとうございました! – JAF

-1

基本的には、あなたのデータ要素をGroupNameの同じ値を持つグループに分けることです。 1つの要素を取りたいすべてのグループ、つまりプロパティ値が最大値のMemberValueのグループから選択します。あなたがアイテムの配列を有し、そしてあなたがEnumerable.GroupBy

「GROUPBY」を使う順番に基づいて、一方をグループに項目の1つの以上の特性の値を、このシーケンスを分割したいときはいつでも

1つの入力パラメータを持っています、アイテムを表示するグループの決定で比較するアイテムのプロパティを選択する関数です。

グループ内のすべての要素が同じGroupNameのグループにシーケンスを分割したいとします。

それは何
var groups = mySequence.GroupBy(element => element.GroupName); 

、それはmySequenceのすべての要素プロパティグループ名からとり、とグループ名のこの値を持つ要素のグループに、この要素を置きます。 GroupNameの==「グループ1」を持つすべての要素を持つ

  • グループ:

    あなたの例のデータを使用して、次の3つのグループがあるでしょう。シーケンスの最初の2つの要素はこのグループになります

    • GroupName == "Group2"のすべての要素を持つグループです。あなたのシーケンスの3番目と4番目の要素は、このグループ
    • にGroupNameの==「グループ3」を持つすべての要素を持つグループになります。あなたのシーケンスの最後の2つの要素は各グループがあなたの選択値を含む、プロパティのキーを持っているこのグループ

になります。このキーはグループを識別し、グループのコレクション内で一意であることが保証されています。 Key == "Group1"のグループ、Key == "Group2"のグループなどがあります。

Keyのほかに、すべてのグループはグループ内の要素のシーケンスです(注:グループはそれが、列挙シーケンスされていない列挙配列を有している。

あなたの第2のステップは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

+0

これは、それぞれの 'GroupName'に最大' MemberValue'を与えます。 OPは最大 'GroupValue'を持つ行と、最大' MemberValue'を持つそれぞれの 'MemberName'を必要とします。 – juharr

関連する問題