C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: 独自のリスト型のデータをまとめる方法


(過去ログ 173 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■99699 / inTopicNo.1)  独自のリスト型のデータをまとめる方法
  
□投稿者/ 河童 (9回)-(2022/05/15(Sun) 15:02:35)

分類:[C#] 

データベースから取得したデータをリストにセット。
そのリストからさらに集計用選択リストを作成したいと思っています。

集計用選択リストは、データリストの「Koumoku2Num」が変わったときに、
「KirokuNum」を条件として作成したいです。 
日付によっては、記録数が異なる場合がありますが、
集計リストの構成は同じにしたいです(記録がない場合は「空白」)。

わからない点は、データリストの繰り返し処理をどうのようにするかです。
・「Koumoku2Num」の判定方法
・集計用選択リストにデータを追加するタイミング

集計用選択リストのクラスを初期化したとき、1つのデータしか入力できません。

集計用選択リストの作成方法をご教示ください。よろしくお願いします。

・テーブルの構成
データ(主キー:id, date, KoumokuNum, Koumoku2Num, Koumoku3Num, KirokuNum)
id	date   KoumokuNum Koumoku2Num Koumoku3Num KirokuNum kiroku
1001	20220510 3      2      1	    0	   
1001	20220510 3      2      1      1     10
1001	20220510 3	   2      1      2     9
1001	20220510 3      2      1       3	  100
1001	20220510 3      4       1	    0	  
1001	20220510 3      4      1      1      8
1001	20220510 3      4       1       2      7
1001	20220510 3      4       1       3      200
1001	20220515 3      2       1	    0	   
1001	20220515 3      2      1      1      6
1001	20220515 3      2       1       2      5

・希望のリスト
id	date   KoumokuNum Koumoku2Num Koumoku3Num kirokuNum1kiroku kirokuNum2kiroku kirokuNum3kiroku 
1001	20220510 3      2      1	    10        9                100
1001	20220510 3      4      1	    8         7                200
1001	20220515 3      2      1	    6         5                
	
       public List<KoumokuData> KoumokuDataLst;
        public class KoumokuData
        {
            public string id { get; set; }
            public string date { get; set; }
            public string koumokuNum { get; set; }
            public string koumoku2Num { get; set; }
            public string koumoku3Num { get; set; }
            public string kirokuNum { get; set; }
            public string kiroku { get; set; }

        }

        public List<KirokuSelected> KirokuSelectedLst;
        public class KirokuSelected
        {
            public string id { get; set; }
            public string date { get; set; }
            public string koumokuNum { get; set; }
            public string koumoku2Num { get; set; }
            public string koumoku3Num { get; set; }
            public string kirokuNum1kiroku { get; set; }
            public string kirokuNum2kiroku { get; set; }
            public string kirokuNum3kiroku { get; set; }
        }

        void CreateKirokuLst()
        {

            // サンプル記録データ(テーブルのデータをリストにセット)
            KoumokuDataLst = new List<KoumokuData>();
            KoumokuData d1  = new KoumokuData();
            d1.id = "1001";
            d1.date = "20220510";
            d1.koumokuNum = "3";
            d1.koumoku2Num = "2";
            d1.koumoku3Num = "1";
            d1.kirokuNum = "0";
            d1.kiroku = "";
            KoumokuDataLst.Add(d1);
            KoumokuData d2= new KoumokuData();
            d2.id = "1001";
            d2.date = "20220510";
            d2.koumokuNum = "3";
            d2.koumoku2Num = "2";
            d2.koumoku3Num = "1";
            d2.kirokuNum = "1";
            d2.kiroku = "10";
            KoumokuDataLst.Add(d2);
            KoumokuData d3 = new KoumokuData();
            d3.id = "1001";
            d3.date = "20220510";
            d3.koumokuNum = "3";
            d3.koumoku2Num = "2";
            d3.koumoku3Num = "1";
            d3.kirokuNum = "2";
            d3.kiroku = "9";
            KoumokuDataLst.Add(d3);
            KoumokuData d4 = new KoumokuData();
            d4.id = "1001";
            d4.date = "20220510";
            d4.koumokuNum = "3";
            d4.koumoku2Num = "2";
            d4.koumoku3Num = "1";
            d4.kirokuNum = "3";
            d4.kiroku = "100";
            KoumokuDataLst.Add(d4);

            KoumokuData d5 = new KoumokuData();
            d5.id = "1001";
            d5.date = "20220510";
            d5.koumokuNum = "3";
            d5.koumoku2Num = "4";
            d5.koumoku3Num = "1";
            d5.kirokuNum = "0";
            d5.kiroku = "";
            KoumokuDataLst.Add(d5);
            KoumokuData d6 = new KoumokuData();
            d6.id = "1001";
            d6.date = "20220510";
            d6.koumokuNum = "3";
            d6.koumoku2Num = "4";
            d6.koumoku3Num = "1";
            d6.kirokuNum = "1";
            d6.kiroku = "8";
            KoumokuDataLst.Add(d6);
            KoumokuData d7 = new KoumokuData();
            d7.id = "1001";
            d7.date = "20220515";
            d7.koumokuNum = "3";
            d7.koumoku2Num = "4";
            d7.koumoku3Num = "1";
            d7.kirokuNum = "2";
            d7.kiroku = "7";
            KoumokuDataLst.Add(d7);
            //KoumokuData d8 = new KoumokuData();
            //d8.id = "1001";
            //d8.date = "20220515";
            //d8.koumokuNum = "3";
            //d8.koumoku2Num = "4";
            //d8.koumoku3Num = "1";
            //d8.kirokuNum = "3";
            //d8.kiroku = "200";
            //KoumokuDataLst.Add(d8);

            // 選択した記録データのリスト
            // Koumoku2Numが変わるごとに記録データを作成
            // 条件:記録番号が「1」「2」「3」3種類
            // 注意:日によっては、記録番号が3種類ないときもある
            KirokuSelectedLst = new List<KirokuSelected>();
            KirokuSelected sd = new KirokuSelected();

            // わからない点:繰り返しの条件とリストに追加するタイミング
            for (int i = 0; i < KoumokuDataLst.Count; i++)
            {
                sd.id = KoumokuDataLst[i].id;
                sd.date= KoumokuDataLst[i].date;
                sd.koumokuNum = KoumokuDataLst[i].koumokuNum;
                sd.koumoku2Num = KoumokuDataLst[i].koumoku2Num;
                sd.koumoku3Num = KoumokuDataLst[i].koumoku3Num;

		// Koumoku2Numが変わるごとに記録データを作成
                switch (KoumokuDataLst[i].kirokuNum)
                {
                    case "1":
                        sd.kirokuNum1kiroku = KoumokuDataLst[i].kiroku;
                        break;
                    case "2":
                        sd.kirokuNum2kiroku = KoumokuDataLst[i].kiroku;
                        break;
                    case "3":
                        sd.kirokuNum3kiroku = KoumokuDataLst[i].kiroku;
                        break;
                    default:
                        break;
                }

                sd.koumokuNum = KoumokuDataLst[i].koumokuNum;

            }
            KirokuSelectedLst.Add(sd);

        }

引用返信 編集キー/
■99700 / inTopicNo.2)  Re[1]: 独自のリスト型のデータをまとめる方法
□投稿者/ 伝説のカレー (10回)-(2022/05/15(Sun) 18:16:13)
No99699 (河童 さん) に返信

こうかな
https://paiza.io/projects/dSwQ5EPavOAUM4MkKXPqog
引用返信 編集キー/
■99701 / inTopicNo.3)  Re[2]: 独自のリスト型のデータをまとめる方法
□投稿者/ 伝説のカレー (11回)-(2022/05/15(Sun) 21:53:09)
LINQ使った方が簡単かも
https://paiza.io/projects/mjNWIKsq8spAqHdA8M-aPA

引用返信 編集キー/
■99707 / inTopicNo.4)  Re[1]: 独自のリスト型のデータをまとめる方法
□投稿者/ 魔界の仮面弁士 (3363回)-(2022/05/16(Mon) 11:03:17)
No99699 (河童 さん) に返信
> データベースから取得したデータをリストにセット。
> そのリストからさらに集計用選択リストを作成したいと思っています。
(1) koumoku1Num ではなく koumokuNum という非対称的な項目名なのは仕様ですか?
(2) KoumokuData に引数付きコンストラクターをオーバーロードしておいた方が楽ですよ。
(3) サンプル作成の「void CreateKirokuLst()」は、フィールド変数へ依存しないよう、
  「List<KirokuSelected> CreateKirokuLst(List<KoumokuData> koumokuDataLst)」
  とした方が入出力対象が明確になると思います。

…というのは本題ではないので放置して:


> 記録がない場合は「空白」
null ではなく "" にするということですかね?


> // 条件:記録番号が「1」「2」「3」3種類
実際は上記のほか、区切りとして無視される "0" が混入しているようですが、
万が一 "0", "1", "2", "3" 以外が来た場合は、エラー扱いで良いですよね?


> 集計用選択リストは、データリストの「Koumoku2Num」が変わったときに、
> 「KirokuNum」を条件として作成したいです。  
kiroku 以外の id,date,KoumokuNum,Koumoku2Num,Koumoku3Num,KirokuNum までが主キーなのですよね?
だとしたら、Koumoku2Num までが同じで、Koumoku3Num が異なっていた場合が
未定義となっています。たとえば下記のような場合の集計結果が曖昧です。

id    date      KoumokuNum  Koumoku2Num  Koumoku3Num  KirokuNum  kiroku
1001  20220510  3           2            1            0
1001  20220510  3           2            1            1          10
1001  20220510  3           2            3            0
1001  20220510  3           2            3            1          15
1001  20220510  3           2            3            2          14

ひとまず今回は Koumoku3Num が "1" 固定のようでしたので、
主キーが id,date,KoumokuNum,Koumoku2Num,Koumoku3Num,KirokuNum の場合と
主キーが id,date,KoumokuNum,Koumoku2Num,KirokuNum の場合で結果は同じですが…。


public List<KoumokuData> KoumokuDataLst;
public List<KirokuSelected> KirokuSelectedLst;

void CreateKirokuLst()
{
    // サンプル記録データ(テーブルのデータをリストにセット)
    var KoumokuDataLst = new List<KoumokuData>();
    // サンプルを作りやすいよう、KoumokuData クラスには
    // 引数付きのコンストラクターもオーバーロードしてあります。
    //   public KoumokuData()
    //   public KoumokuData(string id, string date, string koumokuNum, string koumoku2Num, string koumoku3Num, string kirokuNum, string kiroku)
    KoumokuDataLst.Add(new KoumokuData("1001", "20220510", "3", "2", "1", "0", ""   ));
    KoumokuDataLst.Add(new KoumokuData("1001", "20220510", "3", "2", "1", "1", "10" ));
    KoumokuDataLst.Add(new KoumokuData("1001", "20220510", "3", "2", "1", "2", "9"  ));
    KoumokuDataLst.Add(new KoumokuData("1001", "20220510", "3", "2", "1", "3", "100"));
    KoumokuDataLst.Add(new KoumokuData("1001", "20220510", "3", "4", "1", "0", ""   ));
    KoumokuDataLst.Add(new KoumokuData("1001", "20220510", "3", "4", "1", "1", "8"  ));
    KoumokuDataLst.Add(new KoumokuData("1001", "20220510", "3", "4", "1", "2", "7"  ));
    KoumokuDataLst.Add(new KoumokuData("1001", "20220510", "3", "4", "1", "3", "200"));
    KoumokuDataLst.Add(new KoumokuData("1001", "20220515", "3", "2", "1", "0", ""   ));
    KoumokuDataLst.Add(new KoumokuData("1001", "20220515", "3", "2", "1", "1", "6"  ));
    KoumokuDataLst.Add(new KoumokuData("1001", "20220515", "3", "2", "1", "2", "5"  ));

    KirokuSelectedLst = new List<KirokuSelected>();

    // 選択記録データのリスト側の主キーが、4 つなのか 5 つなのかが現仕様からは読み取れませんでした。
    // そのため今回は、koumoku2Num だけでなく koumoku3Num もグループ化しています
    var dict = new Dictionary<(string id, string date, string koumokuNum, string koumoku2Num, string koumoku3Num), KirokuSelected>();
    KoumokuDataLst.GroupBy(x =>
    {

        // Dictionary のキーに ValueTuple を使っているため、.NET Framework 4.7 以降が対象です。
        var key = (x.id, x.date, x.koumokuNum, x.koumoku2Num, x.koumoku3Num);  // 複合キーを ValueTuple で表現しています
        if (!dict.TryGetValue(key, out var item))
        {
            dict.Add(key, item = new KirokuSelected
            {
                id = x.id,
                date = x.date,
                koumokuNum = x.koumokuNum,
                koumoku2Num = x.koumoku2Num,
                koumoku3Num = x.koumoku3Num,  // ←koumoku3Num をキーにすべきかは疑問なので、ここは要確認。
                kirokuNum1kiroku = "",
                kirokuNum2kiroku = "",
                kirokuNum3kiroku = "",        // 記録がない場合に「""」にするか「null」にするかはお好みで。
            });
            KirokuSelectedLst.Add(item);      // 「選択記録データのリスト」に追加する
        }
        switch (x.kirokuNum)    // Koumoku2Numが変わるごとに記録データを作成します。
        {
            case "0": break;    // 条件:記録番号が「1」「2」「3」3種類。「0」は区切り用なので無視します。
            case "1": item.kirokuNum1kiroku = x.kiroku; break;
            case "2": item.kirokuNum2kiroku = x.kiroku; break;
            case "3": item.kirokuNum3kiroku = x.kiroku; break;
            default: throw new IndexOutOfRangeException(nameof(KoumokuData.kirokuNum));
        }
        return item;
    }).ToArray();
}

引用返信 編集キー/
■99718 / inTopicNo.5)  Re[2]: 独自のリスト型のデータをまとめる方法
□投稿者/ 河童 (10回)-(2022/05/17(Tue) 17:07:24)
伝説のカレー様、魔界の仮面弁士様
アドバイスありがとうございました。

本番環境とデータでやっと期待通りの処理を作成することができました。

今回は、伝説のカレー様の最初のアドバイスで作成できました。
LINQは自分のスキルがなくて、応用ができずに難しかったです。


開発環境がVS2016、VS2019、VS2022とバラバラで
今後はVS2022にバージョンアップしたい
.NET Framework 4.7 もあまり理解できておらず、
今まで動作していたプログラムを動作しなくなり困ってします。


解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -