質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.21%

Listや内部クラスを持ったクラスにLinqを使い、条件検索と値の追加(add)をする方法

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 117

hiro.888

score 1

前提・実現したいこと

C#を使った開発をしています。(.NET Framework 4.7.2)

ある多重構造のclassの子classに含まれるListに対して、
値を値を追加しようと思っています。

foreachでは、実現出することが出来たのですが、可能であれば、linqを利用してシンプルなコートに変更しようと思っています。

当方いろいろ試したのですが、うまくデータを書き換えることが出来ず、苦戦しております。
皆様の知恵をお借りできないでしょうか。

linqを使わずに行った場合(現在出来ている)

クラス

    public class student
    {
        public int id;
        public string name;
        public List<testResult> testResults = new List<testResult>();

    }

    public class testResult
    {
        public int times;
        public int score;
    }

サンプルデータ

        // サンプルデータを作成
        static List<student> createSampleData()
        {
            var student = new student();
            var testResult = new testResult();
            var students = new List<student>();

            //サンプル作成(Aさん)
            student = new student();
            student.id = 1;
            student.name = "A";

            //1回目テスト
            testResult = new testResult();
            testResult.times = 1;
            testResult.score = 30;
            student.testResults.Add(testResult);

            //2回目テスト
            testResult = new testResult();
            testResult.times = 2;
            testResult.score = 40;
            student.testResults.Add(testResult);

            //3回目テスト
            testResult = new testResult();
            testResult.times = 3;
            testResult.score = 50;
            student.testResults.Add(testResult);

            students.Add(student);

            //サンプル作成(Bさん)
            student = new student();
            student.id = 2;
            student.name = "B";

            //1回目テスト
            testResult = new testResult();
            testResult.times = 1;
            testResult.score = 90;
            student.testResults.Add(testResult);

            //2回目テスト
            testResult = new testResult();
            testResult.times = 2;
            testResult.score = 80;
            student.testResults.Add(testResult);

            students.Add(student);

            return students;
        }

実際のロジック

        static void Main(string[] args)
        {
            // サンプルデータ取得
            var students = createSampleData();

            //本題
            //ID:2のBさんの3回目テスト結果(99点)を追加する
            var testResult = new testResult();
            testResult.times = 3;
            testResult.score = 99;

            //Linqに置き換えたい部分 ↓
            foreach (var student in students)
            {
                if (student.id == 2)
                {
                    student.testResults.Add(testResult);
                }
            }
            //Linqに置き換えたい部分 ↑
        }

試したこと

students.Where(student => student.id == 2).…


whereを使いBさんの絞り込みまでは出来ているが、この跡list(testResults)にデータを追加(add)する方法が見つからないです。

students.Where(student => student.id == 2).Select(x => x.testResults = x.testResults.Append(testResult).ToList());


このような形を試してみましたが間違いのようでした。色々と検索をしているのですが、解決策が見いだせず苦戦しております。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • hiro.888

    2020/05/23 15:12

    そうなんですね。一旦試してみます。ありがとうございます。

    キャンセル

  • hiro.888

    2020/05/23 16:58

    Zuishinさん
    dictionaryでの実装がうまくいきました。ありがとうございました。

    ただ、後学のため、タイトルの通りLinqでのコーディングも引き続き調査したいと思います。
    ご存知の方がいらっしゃればアドバイスをいただければと思います。

    キャンセル

  • hihijiji

    2020/05/23 17:58

    LINQが使いにくい場面は、LINQを使うべきではない場面です。

    キャンセル

回答 2

checkベストアンサー

+2

こんにちは。

質問に対する回答ではないですが、
まず、Linq がやるべきことは、その名前の通り Query であり、「リストに Add する」などの Action に相当する処理は Linq で行うべきではないものと考えます。

この質問に記載された「実際のロジック」からその本来の意図を読み取ると、「students から id == 2 である student を抽出する」と読み替えることができるため、以下のように書くのが良いと思います。
Linq 本来の目的の一つである、処理の意図を明らかにし、不要なループを除去するという目的は達成できています。

// id == 2 である student を手に入れる
var target = students.Single(student => student.id == 2);

// testResult を target に追加
target.testResults.Add(testResult);

ただし、今回のような用途では、id を元に Dictionary を作った方が良いのは追記修正にもある通りです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/05/24 12:01 編集

    ご回答ありがとうございます。

    皆さんお答えのようにやはりDictionaryのkeyをうまく使ったほうが良いということですね。

    サンプルコードもありがとうございます。

    今回はid=ユニークなコードで例を出していたのですが、実際のコードでは、idの部分がユニークではない場合、複合キー(Tupleが必要?)の場合、id==2 ではなく、id <= 2 のような範囲で使用することもあり、書き方の幅を広げたいと思っての質問でした。

    大変参考になりました。

    キャンセル

  • 2020/05/24 12:05

    ldを重複させるつもりはないということでしょうが、元ロジックと等価ではない点は注意が必要です。

    キャンセル

+1

私は好きではありませんが、手軽にやるならこうとか?

students.Where(s => s.id == 2).ToList().ForEach(s => s.testResults.Add(testResult));

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/05/24 12:03

    ご回答ありがとうございます。

    サンプルコードありがとうございます。

    かけないことはないということですね。
    ただ、あまり適切ではない書き方ということも、勉強になりました。

    大変参考になりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる
  • トップ
  • C#に関する質問
  • Listや内部クラスを持ったクラスにLinqを使い、条件検索と値の追加(add)をする方法