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

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

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

2つのリストから1つのリストを作成する方法

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

■90487 / inTopicNo.1)  2つのリストから1つのリストを作成する方法
  
□投稿者/ 河童 (42回)-(2019/03/14(Thu) 13:18:49)

分類:[C#] 

いつも大変お世話になっております。

2つのリストのデータから新たに1つのリストを作成したいです。

2つのリストとは、
・利用者マスタのリスト(userList)
・利用者の日々のデータ(d_dataList )
です。

作りたいリスト
・利用者の1ヵ月間のデータを1行にまとめたもの
です。


わからないことは、
日々のデータの繰り返しの処理の中で
データを横から縦に変更する処理です。
また利用者マスタと日々のデータの紐付け方法が
分かりません。

d_dataList 
data user_id taion
1    1       36
2    1       38
3    1       39
1    2       35
2    2       37
3    2       36

作りたいリスト
user_id user_name day1 day2 day3
1       testA     36   38   39 
2       testB     35   37   36

日々のデータを
利用者ごと(1ヵ月分)にまとめた
リストが作成したいです。
   

    public class UserInfo
    {
        public string user_id { get; set; }
        public string user_name { get; set; }
        public string user_kana { get; set; }
        public string day1 { get; set; }
        public string day2 { get; set; }
        public string day3 { get; set; }
      // 31日まで(省略)

    }

    public class m_User
    {
        public string user_id { get; set; } 
        public string user_name { get; set; }
        public string user_kana { get; set; }
    }
   
    public class d_data
    {
        public string date { get; set; }
        public string user_id { get; set; }
        public string taion { get; set; }
    }

    public List<d_data> d_dataList = new List<d_data>();
    public List<m_User> userList = new List<m_User>();


        private void Frm_List_Load(object sender, EventArgs e)
        {

            // データグリッドのソース作成  
            List<UserInfo> list = new List<UserInfo>();

            UserInfo uf = new UserInfo();
            foreach (d_data d in d_dataList)
            {

                uf.user_id = d.user_id;
                uf.user_name = m.user_name; //?user_idとuser_nameをどのように紐づけるか               
		
		uf.day1 = d.taion //?dateが「1」のときに、day1に体温をセットしたいです。 		

                list.Add(uf);

            }


            // ソースセット
            this.dgvRiyojoho.DataSource = list;

        }

引用返信 編集キー/
■90488 / inTopicNo.2)  Re[1]: 2つのリストから1つのリストを作成する方法
□投稿者/ 魔界の仮面弁士 (2110回)-(2019/03/14(Thu) 15:18:27)
No90487 (河童 さん) に返信
> uf.day1 = d.taion //?dateが「1」のときに、day1に体温をセットしたいです。

"1" という文字列から day1 プロパティにアクセスしようとすると、
リフレクション頼りになってしまいますね。

この場合は UserInfo クラスに手を加えて、
 uf.day[d.date] = d.taion;
あるいは
 uf[d.date] = d.taion;
の形でアクセスできるよう改修してみては如何でしょう?




private void Form1_Load(object sender, EventArgs e)
{
  #region サンプルデータ
  d_dataList = new List<d_data>
  {
    new d_data { date = "1", user_id = "1", taion = "36"},
    new d_data { date = "2", user_id = "1", taion = "38"},
    new d_data { date = "3", user_id = "1", taion = "39"},
    new d_data { date = "1", user_id = "2", taion = "35"},
    new d_data { date = "2", user_id = "2", taion = "37"},
    new d_data { date = "3", user_id = "2", taion = "36"},
  };
  userList = new List<m_User>
  {
    new m_User { user_id = "1", user_name = "testA", user_kana = null },
    new m_User { user_id = "2", user_name = "testB", user_kana = null },
  };
  #endregion

  // データグリッドのソース作成
  var dictList = userList.ToDictionary(k => k.user_id);
  List<UserInfo> list = d_dataList
    .GroupBy(x => x.user_id, x => new { x.date, x.taion })
    .Select(y => new UserInfo(y.ToDictionary(k => k.date, v => v.taion))
    {
      user_id = dictList[y.Key].user_id,
      user_name = dictList[y.Key].user_name,
      user_kana = dictList[y.Key].user_kana
    }).ToList();

  // ソースセット
  this.dgvRiyojoho.DataSource = list;
}


public class UserInfo
{
  private readonly Dictionary<string, string> days;
  public UserInfo() { this.days = new Dictionary<string, string>(); }
  public UserInfo(IDictionary<string, string> days) { this.days = new Dictionary<string, string>(days); }
  private string getDay(string d) { return days.ContainsKey(d) ? days[d] : null; }

  public string user_id { get; set; }
  public string user_name { get; set; }
  public string user_kana { get; set; }

  public string day1 { get { return getDay("1"); } set { days["1"] = value; } }
  public string day2 { get { return getDay("2"); } set { days["2"] = value; } }
  public string day3 { get { return getDay("3"); } set { days["3"] = value; } }
  public string day4 { get { return getDay("4"); } set { days["4"] = value; } }
  // 以下略
}
引用返信 編集キー/
■90489 / inTopicNo.3)  Re[2]: 2つのリストから1つのリストを作成する方法
□投稿者/ 魔界の仮面弁士 (2111回)-(2019/03/14(Thu) 15:54:47)
No90487 (河童 さん) に返信
> ・利用者の1ヵ月間のデータを1行にまとめたもの

データ List<d_data> 内の user_id が、利用者リスト List<m_User> に無かった場合や、
利用者リスト List<m_User> には居るけれど、taion データ List<d_data> に記録の無い人が
あった場合を考慮する必要があるかどうかも気になるところ。



No90488 (魔界の仮面弁士) に追記
> "1" という文字列から day1 プロパティにアクセスしようとすると、
> リフレクション頼りになってしまいますね。
>
> この場合は UserInfo クラスに手を加えて、

リフレクション頼みの別案。
今回の UserInfo クラスは、元の No90487 の実装のままにしています。



Action<UserInfo, string, string> setter = (target, date, taion) => typeof(UserInfo).GetProperty("day" + date).SetValue(target, taion, null);

Dictionary<string, UserInfo> dic = userList.ToDictionary(
  k => k.user_id,
  v => new UserInfo { user_id = v.user_id, user_kana = v.user_kana, user_name = v.user_name });
foreach (d_data d in d_dataList)
{
  UserInfo uf;
  if(dic.TryGetValue(d.user_id, out uf)) { setter(uf, d.date, d.taion); }
}

List<UserInfo> list = new List<UserInfo>(dic.Values);

this.dgvRiyojoho.DataSource = list;
引用返信 編集キー/
■90490 / inTopicNo.4)  Re[3]: 2つのリストから1つのリストを作成する方法
□投稿者/ 河童 (44回)-(2019/03/14(Thu) 16:36:30)
魔界の仮面弁士 さん、お返事ありがとうございます。


追加の仕様で申し訳ありませんが、アドバイスお願いいたします。
d_dataListの内容は、体温の他に血圧、食事の有無などあります。

利用者リスト List<m_User> には居るけれど、
データ List<d_data> に記録の無い人が居る場合はあります。

フォームに表示条件(体温、血圧、食事)を設置して
表示条件に合わせたリストを作成したいです。


表示条件ごとに、同じようにUserInfoクラスを
作成するべきでしょうか?


まだデータグリッドビューのソースにセットするリストの型を
バインディングリストにしたいと思っています。

[Serializable] //追加しました
public class UserInfo


BindingList<UserInfo> list = d_dataList
型を変更すると
.ToList();
の箇所で暗黙的に変換できないとエラーがでます。

d_dataList
data user_id taion ketuatu syokuji
1 1 36 100 ○
2 1 38 102 ○
3 1 39
1 2 35 110 ○
2 2 37 112 ○
3 2 36


作りたいリスト(体温)
user_id user_name day1 day2 day3
1 testA 36 38
2 testB 35 37

作りたいリスト(血圧)
user_id user_name day1 day2 day3
1 testA 100 102
2 testB 110 112

作りたいリスト(食事)
user_id user_name day1 day2 day3
1 testA ○ ○
2 testB ○ ○

引用返信 編集キー/
■90491 / inTopicNo.5)  Re[4]: 2つのリストから1つのリストを作成する方法
□投稿者/ 魔界の仮面弁士 (2112回)-(2019/03/14(Thu) 17:18:22)
No90490 (河童 さん) に返信
> 表示条件ごとに、同じようにUserInfoクラスを
> 作成するべきでしょうか?

表示条件がどのように切り替わるのかがイメージできませんでした。

DataGridView に表示する場合に、体温グリッド、血圧グリッド、食事グリッドと分けて表示したいのか、
あるいは一つの表に、taion1〜taion31、shokuji1〜shokuji31 などと横方向に並べていきたいのか、
あるいは一人一人が複数のレコードで表現されていて
 1  testA  体温   36   38   39
 1  testA  血圧 134/71 115/76 118/72
 2  testB  体温   35   37   36
のように縦方向に積み上げていくのか、それとも…?


仕様が読み切れなかったので具体例は示せませんが、表示条件が可変なら、
XDocument とか DataTable とか Dictionary とかを用いた方が取り回しやすいと思います。
DataGridView が対象なら、DataTable を使うのが楽かもしれません。


もしも UserInfo で管理するなら、体温、血圧、食事などすべての情報を保持できるようにしておいた方が良いでしょう。
その場合、DataGridView に表示する際に、表示項目を制限するということもできます。

dgvRiyojoho.AutoGenerateColumns = false; にして、列のバインドを自分で行わせても良いし、
dgvRiyojoho.AutoGenerateColumns = true; にしてバインド後に不要な列を Visible = false にするのも良し。


> まだデータグリッドビューのソースにセットするリストの型を
> バインディングリストにしたいと思っています。
BindingList<T> のことですね。


> BindingList<UserInfo> list = d_dataList
> 型を変更すると
> .ToList();
> の箇所で暗黙的に変換できないとエラーがでます。

えぇと???

当初の質問では、d_dataList は
「List<d_data> d_dataList」な変数でしたよね。

それを
 BindingList<UserInfo> list = d_dataList;
にするのは無理があると思うのですが…。


d_dataList 変数を BindingList<UserInfo> にすれば代入できますが、それだと話が繋がらないですし、
d_dataList 変数が List<UserInfo> だとしたら、代入式の右辺は new BindingList<UserInfo>(d_dataList) でしょう。


前提条件が分からないので、何に対して .ToList() しようとしているのか読み解けませんでしたが、
ToList できないなら、foreach で列挙して、適当な List<> 変数に Add していく方法は使えませんか?
引用返信 編集キー/
■90530 / inTopicNo.6)  Re[5]: 2つのリストから1つのリストを作成する方法
□投稿者/ 河童 (46回)-(2019/03/18(Mon) 15:02:24)
No90491 (魔界の仮面弁士 さん) に返信

魔界の仮面弁士さん、ありがとうございました。
仕様、要望が変わって申し訳ありませんでした。


一ヶ月分のリストの変数に、セットしたい条件をSwitchして
設定しました。

とりあえず、やりたいことはできるようになりました。

今回の件でリストの理解を


foreach (m_User ul in userList)
{
// 利用者
var list1 = d_dataList.Where(n => n.user_id == ul.user_id).ToList();

// 日付(1ヵ月分)
List<string> list3 = new List<string>(31);
for (int i = 1; i <= 31; i++)
{
list1.Where(n => n.date == + i).ToList();
if (list1.Count > 0)
{
switch (hyoji_select)
{
case "送迎":
list3.Add(list1[i - 1].sougei);
break;

case "バイタル": // バイタル(体温、血圧)
list3.Add(list1[i - 1].taion + Environment.NewLine +
list1[i - 1].ketuatu + "/" +list1[i - 1].ketuatu);
break;

}
}
else
{
list3.Add("");
}
}
UserInfo ui = new UserInfo();
ui.user_id = ul.user_id;
ui.user_name = ul.user_name;
ui.day1 = list3[0];
ui.day2 = list3[1];
ui.day3 = list3[2];
ui.day4 = list3[3];
ui.day5 = list3[4];

list.Add(ui);

}

this.dgvRiyojoho.DataSource = list;


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

このトピックをツリーで一括表示


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

このトピックに書きこむ