

いつも勉強させていただいています。本日は皆様のお知恵を拝借させていただければと思って  
質問いたします。

[code]

    public class TestResult {
        public string Kamoku;
        public int Tensu;
    }
    
    public class Grade {
        public int Rank;
        public List<TestResult> result;
    }
    
    public class Peron {
        public int Id;
        public string Name;
        public Dictionary<string, Grade> dic;
    }
    
[/code]

上記のようなクラスがある場合に、Tensuの最大値を取得したいのですが、どのように書けば簡潔に取得できますでしょうか。

Person personalData = new Person() などして各プロパティやディクショナリには  
値を設定済みという前提ですが、

[code]

    int MaxTensu = personalData.dic.Values.Max(x => x.result.Max(y => y.Tensu));
    
[/code]

この書き方では「シーケンスに要素が要素が含まれていません」でエラーになりました。  
↓ のような書き方にするべきでしょうか。よろしくお願いいたします。

[code]

    int max = 0;
    foreach (Grade g in personalData.dic.Values) {
        int i = g.result.Max(x => x.Tensu);
        if (max < i) {
            max = i;
        }
    }
    
[/code]


CC BY-SA 3.0
2017-11-10T15:59:18.150
39481
2018-09-06T02:01:04.840
2017-11-10T16:06:50.967
26142
26142
question
c# linq
LINQを利用して、クラスの中のディクショナリの中のクラスに持つプロパティの最大値を取得したい


(実行効率は別として)考え方は間違ってないと思いますが、`Max`は少なくとも１つ以上の要素を必要とするため、`dic`や`result`の要素が空の場合があるとそのようなエラーになります。

`SelectMany`で一旦平坦化することで、どこかに１つでも`result`の要素があればOKになります。

[code]

    int max = personalData.dic.Values.SelectMany(g => g.result).Max(r => r.Tensu);
    
[/code]

`dic`が空の場合やすべての`result`が空である場合も考慮するなら`DefaultIfEmpty`でデフォルト値を入れるとよいです。

[code]

    int max = personalData.dic.Values.SelectMany(g => g.result)
        .Select(r => r.Tensu).DefaultIfEmpty(0).Max();
    
[/code]


CC BY-SA 3.0
2017-11-10T17:15:30.517
39482
2017-11-10T17:15:30.517
4765
39481
answer


`Enumerable.Max`は`Nullable<T>`型のオーバーロードを使用すると要素がなくても例外が発生しません。ですので一旦`int?`にキャストする手があります。

[code]

    int? MaxTensu = personalData.dic.Values.Max(x => x.result.Max(y => (int?)y.Tensu));
    
[/code]

なお最後に`?? 0`をつけると`0`が既定値になります。


CC BY-SA 3.0
2017-11-11T00:17:42.173
39485
2017-11-11T00:17:42.173
5750
39481
answer