こんにちは。
今回もよろしくお願いいたします。
前提・実現したいこと
LINQにて各データをグループ化してからコンボボックスに格納するプログラムを作成しました。
ここから更にcmbZOK1(コンボボックス)から項目を選択したタイミングで、”cmbZOK1の選択項目が含まれる行のデータ”を抽出・グループ化し、cmbZOK2(コンボボックス)以降に表示したいです。
発生している問題・エラーメッセージ
関数”cmbZOK1_SelectedIndexChanged”内の"groupby~"部分が問題なのではと考えています。どのように条件を設定すれば正しく抽出できますか?
現時点では下記で抽出条件を設定したつもりですが、結果はAddCmbを動作させたときと同じ内容で表示されてしまいます
該当のソースコード
C#
1 public MAIN() 2 { 3 InitializeComponent(); 4 5 6 // テキストデータ読み込み 7 string file = @"C:aaa.csv"; 8 StreamReader sr = new StreamReader(file, Encoding.GetEncoding("SHIFT_JIS")); 9 while (sr.EndOfStream == false) 10 { 11 string line = sr.ReadLine(); 12 string[] linef = line.Split(','); 13 F.Add(linef); 14 15 } 16 sr.Close(); 17 18 // 属性コンボボックスにグループ化した属性をAdd 19 AddCmb(cmbZOK1, 0); // cmbZOK1 20 AddCmb(cmbZOK2, 1); // cmbZOK2 21 AddCmb(cmbZOK3, 2); // cmbZOK3 22 AddCmb(cmbZOK4, 3); // cmbZOK4 23 AddCmb(cmbZOK5, 4); // cmbZOK5 24 AddCmb(cmbZOK6, 5); // cmbZOK6 25 AddCmb(cmbZOK7, 6); // cmbZOK7 26 AddCmb(cmbZOK8, 7); // cmbZOK8 27 AddCmb(cmbZOK9, 8); // cmbZOK9 28 AddCmb(cmbZOK10, 9); // cmbZOK10 29 30 void AddCmb(ComboBox ControlName, int arr) 31 { 32 var query = F.GroupBy(x => x[arr]); 33 foreach (var group in query) 34 { 35 ControlName.Items.Add(group.Key); 36 } 37 } 38 39 } 40 41 42 private void cmbZOK1_SelectedIndexChanged(object sender, EventArgs e) 43 { 44 var query = F.GroupBy(x => new { x = cmbZOK1.Text, y = x[1] }); 45 cmbZOK2.Items.Clear(); 46 foreach (var group in query) 47 { 48 cmbZOK2.Items.Add(group.Key.y); 49 } 50 } 51 52
補足情報
取り込むcsvの内容ですが、下記のような形です。
列1 | 列2 | 列3・・・ |
---|---|---|
エチオピア | グジ | ナチュラル |
エチオピア | グジ | ウォッシュト |
エチオピア | シダモ | ナチュラル |
エチオピア | シダモ | ウォッシュト |
コロンビア | ナリーニョ | ナチュラル |
コロンビア | ナリーニョ | ウォッシュト |
列1(cmbZOK1)で”エチオピア”と選択した場合、列2(cmbZOK2)はグジ、シダモが抽出され、列3にはナチュラル、ウォッシュトが抽出されるイメージです。
今後、列2で項目を選択した場合、列3以降は列1,2で選択した条件で抽出されるようにしたいと考えています。
ソースコード修正後(自分用)
ご回答を元にソースコードを修正し、意図通りに動作しました。
c#
1 public partial class MAIN : Form 2 { 3 4 // クラス内public 5 private List<string[]> F = new List<string[]>(); 6 private List<ComboBox> Cmb = new List<ComboBox>(); //cmbboxを共通関数で扱いやすくするため、リストに入れて覚えておくためのもの 7 8 public MAIN() 9 { 10 InitializeComponent(); 11 12 13 // テキストデータ読み込み 14 string file = @"C:\txt.csv"; 15 StreamReader sr = new StreamReader(file, Encoding.GetEncoding("SHIFT_JIS")); 16 while (sr.EndOfStream == false) 17 { 18 string line = sr.ReadLine(); 19 string[] linef = line.Split(','); 20 F.Add(linef); 21 22 } 23 sr.Close(); 24 25 // 属性コンボボックスにグループ化した属性をAdd 26 AddCmb(cmbZOK1, 0); // cmbZOK1 27 AddCmb(cmbZOK2, 1); // cmbZOK2 28 AddCmb(cmbZOK3, 2); // cmbZOK3 29 AddCmb(cmbZOK4, 3); // cmbZOK4 30 AddCmb(cmbZOK5, 4); // cmbZOK5 31 AddCmb(cmbZOK6, 5); // cmbZOK6 32 AddCmb(cmbZOK7, 6); // cmbZOK7 33 AddCmb(cmbZOK8, 7); // cmbZOK8 34 AddCmb(cmbZOK9, 8); // cmbZOK9 35 AddCmb(cmbZOK10, 9); // cmbZOK10 36 37 void AddCmb(ComboBox ControlName, int arr) 38 { 39 var query = F.GroupBy(x => x[arr]); 40 foreach (var group in query) 41 { 42 ControlName.Items.Add(group.Key); 43 } 44 Cmb.Add(ControlName); //★ここでzok1から10をaddしておく。 45 } 46 47 } 48 49 private void Form1_Load(object sender, EventArgs e) 50 { 51 52 53 } 54 55 private void cmbZOK1_SelectedIndexChanged(object sender, EventArgs e) 56 { 57 Handler(cmbZOK1.Text, 0); 58 } 59 60 private void cmbZOK2_SelectedIndexChanged(object sender, EventArgs e) 61 { 62 Handler(cmbZOK2.Text, 1); 63 } 64 65 private void cmbZOK3_SelectedIndexChanged(object sender, EventArgs e) 66 { 67 Handler(cmbZOK3.Text, 2); 68 } 69 70 private void cmbZOK4_SelectedIndexChanged(object sender, EventArgs e) 71 { 72 Handler(cmbZOK4.Text, 3); 73 } 74 75 private void cmbZOK5_SelectedIndexChanged(object sender, EventArgs e) 76 { 77 Handler(cmbZOK5.Text, 4); 78 } 79 80 private void cmbZOK6_SelectedIndexChanged(object sender, EventArgs e) 81 { 82 Handler(cmbZOK6.Text, 5); 83 } 84 85 private void cmbZOK7_SelectedIndexChanged(object sender, EventArgs e) 86 { 87 Handler(cmbZOK7.Text, 6); 88 } 89 90 private void cmbZOK8_SelectedIndexChanged(object sender, EventArgs e) 91 { 92 Handler(cmbZOK8.Text, 7); 93 } 94 95 private void cmbZOK9_SelectedIndexChanged(object sender, EventArgs e) 96 { 97 Handler(cmbZOK9.Text, 8); 98 } 99 100 private void cmbZOK10_SelectedIndexChanged(object sender, EventArgs e) 101 { 102 Handler(cmbZOK10.Text, 9); 103 } 104 105 // Fから特定列(縦方向)を抜き出す補助関数 106 static IEnumerable<string> PickColumn(IEnumerable<string[]> table, int columnNumber) => table.Select(line => line[columnNumber]); 107 108 // Fから、idx列目までの値を基準に、その手前までを絞る補助関数 109 static IEnumerable<string[]> FilterMulti(IEnumerable<string[]> table, List<ComboBox> cmbboxes, int selectedCmbIdx) => table 110 .Where(line => Enumerable.Range(0, selectedCmbIdx + 1) 111 .All(i => cmbboxes[i].Text == "" || line[i] == cmbboxes.ElementAt(i).Text) ); 112 113 //cmb内容をリセット・グループ化するための補助関数 114 static void ResetItems(ComboBox cmb, IEnumerable<string> items) //★objectだとgroupbyが使えないため、stringに変更 115 { 116 cmb.Items.Clear(); 117 var query = items.GroupBy(x => x); 118 foreach(var group in query) 119 { 120 cmb.Items.Add(group.Key); 121 } 122 123 } 124 125 //CmbZOK1_selectedIndexChangeとかで、このハンドラを呼び、そのとき、Zok1なら0,Zok8なら7という自身のcmbにおけるインデクスと、選択された値を渡してください。 126 void Handler(string selectedText, int selectedCmbIdx) 127 { 128 var filteredF = F.Where(x => x[selectedCmbIdx] == selectedText).ToArray(); 129 var filteredMultiF = FilterMulti(filteredF, Cmb, selectedCmbIdx); 130 131 for (var i = selectedCmbIdx + 1; i < 10; i++) 132 { 133 ResetItems(Cmb[i], PickColumn(filteredMultiF, i)); 134 Cmb[i].Text = string.Empty; 135 } 136 } 137 138 }

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/01/29 02:58
2019/01/29 03:26
2019/01/29 03:29 編集
2019/01/29 03:32
2019/01/29 04:18
2019/01/29 04:34 編集
2019/01/29 04:23
2019/01/29 04:35
2019/01/29 04:40
2019/01/29 04:47
2019/01/29 12:46
2019/01/30 01:18