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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

Q&A

解決済

2回答

3017閲覧

【C#】ToDictionaryの使用方法が不明

k_mail

総合スコア90

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

0グッド

0クリップ

投稿2019/01/05 13:05

編集2019/01/05 13:09

ToDictionaryの使用方法が不明です。
下記は、「実戦で役立つ C#プログラミングのイディオム/定石&パターン」からの抜粋になります。
デバックで中身を見ようとしたのですが、うまくいきませんでした。。。

ご回答可能なもののみで構いませんので、
宜しくお願い致します。

下記の7行目の
_dict = lines.Select(line => line.Split('='))
のみを抜粋すると_dict は、
配列
[0]APEC
[1]アジア太平洋経済協力
[2]ASEAN
[3]東南アジア諸国連合
[4]CTBT
[5]包括的核実験禁止条約
になると思います。

【質問1】
8行目の処理ではどのような処理が行われているのでしょうか。
(具体的にデータがどのように処理されているのでしょうか。)

【質問2】
8行目でなぜ、添え字が[0],[1]の直書きなのでしょうか。

【質問3】
(【質問2】の派生になります) 
なぜ、foreach文を使用せずに、
_dictの中身が、
[0]{[APEC],[アジア太平洋経済協力]}
[1]{[ASEAN],[東南アジア諸国連合]}
[2]{[CTBT],[包括的核実験禁止条約]}
と配列になるのでしょうか。
(逆に【質問2】でforeachと合わせて、添え字をローカル変数iやkにしなくて良いのでしょうか。)

Abbreviations.txtの1行目を読み出し、
1行ずつforeach文で処理をしなければいけないような気がします。
(2行目の
private Dictionary<string, string> _dict = new Dictionary<string, string>();
で、new Dictionary<string**[], string[]**>())
と[]マークがあれば、感覚的に理解できるのですが。。

【質問4】
( 表題と異なりますが、)
Splitに改行の指定はなぜ不要なのでしょうか。
改行を指定しない場合、
_dict = lines.Select(line => line.Split('='))の結果は、
配列
[0]APEC
[1]アジア太平洋経済協力ASEAN
[2]東南アジア諸国連合CTBT
[3]包括的核実験禁止条約
のような形でペアがずれるような気がします。

お手数をお掛け致しますが、
宜しくお願い致します。

C#

11 class Abbreviations { 22 private Dictionary<string, string> _dict = new Dictionary<string, string>(); 33 44 // コンストラクタ 55 public Abbreviations() { 66 var lines = File.ReadAllLines("Abbreviations.txt"); 77 _dict = lines.Select(line => line.Split('=')) 88 .ToDictionary(x => x[0], x => x[1]); 99 } 1010 }

Abbreviations.txt↓

APEC=アジア太平洋経済協力 ASEAN=東南アジア諸国連合 CTBT=包括的核実験禁止条約

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

File.ReadAllLinesメソッドは1行を一つの要素としてstringの配列を返します。
ですので、
lines[0] "APEC=アジア太平洋経済協力"
lines[1] "ASEAN=東南アジア諸国連合"
lines[2] "CTBT=包括的核実験禁止条約"
となります。

よって、_dict = lines.Select(line => line.Split('='))はlinesの各要素を'='で分割したジャグ配列となります。
_dict[0] {"APEC","アジア太平洋経済協力"}
_dict[1] {"ASEAN","東南アジア諸国連合"}
_dict[2] {"CTBT","包括的核実験禁止条約"}

ToDictionaryで、xは_dictの各要素(先ほどの{"APEC","アジア太平洋経済協力"}のstring配列部分)が順番に処理されるかたちとなります。
x => x[0], x => x[1]この部分で、DictionaryのKeyとValueを指定する形になります。

投稿2019/01/05 14:25

編集2019/01/05 14:27
YAmaGNZ

総合スコア10258

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k_mail

2019/01/05 15:22

ご回答ありがとうございます。 ジャグ配列ってこんな時に使われていたんですね。 「C#独習」で一度拝読しましたが、内容はさっぱりでした。 今回、ご説明頂きすっきりしました。 ありがとうございます。
guest

0

ベストアンサー

LinqはC#を使って配列を操作するときには便利な技術なので、覚えておくとよろしいかと思います。

以下回答
便宜上IEnumerable<string>をstring[]と表記します。

【回答4】
File.ReadAllLinesの時点で改行文字で分割されてlinesに格納されているためです。
この時点でlinesには

[0] APEC=アジア太平洋経済協力 [1] ASEAN=東南アジア諸国連合 [2] CTBT=包括的核実験禁止条約

が入ります。

【回答1】

C#

1lines.Select(line => line.Split('='));

の意味ですが、lines(string[])の要素一つずつをline(string)に格納し、line.Split('=')を通した値に変換しています。
この時点で、一旦変数に格納すると、

[0][0] APEC, [1] アジア太平洋経済協力 [1][0] ASEAN, [1] 東南アジア諸国連合 [2][0] CTBT, [1] 包括的核実験禁止条約

になります。

【回答2】
ToDictionaryでは、【回答1】までで作られた配列(string[][])の要素一つずつをx(string[])に格納し、x[0]をキー、x[1]を値としてDictionaryを作成しています。

x[0] APEC x[1] アジア太平洋経済協力

これで回答になっているでしょうか。

投稿2019/01/05 14:07

nanase

総合スコア123

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k_mail

2019/01/05 15:25 編集

ご回答ありがとうございます。 x => x[0], x => x[1]が示していたものって これのことだったのですね。大変わかりやすかったです。   ↓これ(x[0]) ↓これ(x[1]) [0][0] APEC,   [1] アジア太平洋経済協力 [1][0] ASEAN, [1] 東南アジア諸国連合 [2][0] CTBT, [1] 包括的核実験禁止条約 _dict = lines.Select(line => line.Split('=')) .ToDictionary(x => x[0], x => x[1]); についてですが、 i )「.ToDictionary」は即時実行なのでしょうか。 (「.toarray」「.toList」は即時実行とどこかでみたような気がします。。。) ii) なぜ最後まで、実行されるのでしょうか。 (なぜ1回で終わらず、すべて実行されるのでしょうか。)   Selectがあれば、foreachは不要という理解で良いでしょうか。 私は下記のようなコードではないといけないのでは?と感じています。 (イメージです。動かないですが。。。1こずつとりだして変数に代入) _dict = foreach(var line in lines.Split('=').ToDictionary(x => x[0], x => x[1]);
nanase

2019/01/05 15:41

i) これの答えは、YESです。 Linqは遅延実行の仕組みを持っていて、値が必要になるまで実行されませんが、おっしゃられている通り、ToArray,ToList,ToDictionaryをした時点で実行されます。 ```C# var ie = lines.Select(line => line.Split('=')); // まだ実行されない(IEnumerable型) _dict = ie.ToDictionary(x => x[0], x => x[1]); // ここでDictionary型に変換するためにSelectも含めて実行される ``` ii) そうですね、今回の場合で言えばforeachは必要ありません。 なぜかと聞かれると少し困ってしまうのですが、今回のLinqのコードをforeachに変換すると、厳密にはi)の質問であったような即時実行される/されないなどの違いはあるのですが、概ね以下のようになります。 ```C# // Linq版 // lines(string[])をlines2(string[][])に変換 var lines2 = lines.Select(line => line.Split('=')); // lines2のそれぞれの要素の1番目をキー、2番目を値としてDictionary型に変換 var _dict = lines2.ToDictionary(x => x[0], x => x[1]); // foreach版 // lines(string[])をlines2(string[][])に変換 var lines2 = new List<string[]>(); foreach(var line in lines){ lines2.Add(line.Split('=')); } // lines2のそれぞれの要素の1番目をキー、2番目を値としてDictionary型に変換 var _dict = lines2.ToDictionary(x => x[0], x => x[1]); ``` ```C# line => line.Split('=') ``` や、 ```C# x => x[0] x => x[1] ``` の部分が要素の数だけ実行されるという点がわかりづらいポイントでしょうか。
k_mail

2019/01/05 16:01

>line => line.Split('=') >や、 >x => x[0] >x => x[1] >の部分が要素の数だけ実行されるという点がわかりづらいポイントでしょうか。 ⇒はい!!その通りです。それが言いたかったです)汗  いったんは、要素の分だけ実行される、という暗記する、ということでクローズします。  foreach版も記載いただきありがとうございます。  また、理解を助けるヒントのようなものがあれば、ご回答お願い致します。  ありがとうございました。
nanase

2019/01/06 00:05

この部分はラムダ式と言って、メソッドを簡略化して表記しているだけです。 line => line.Split('=')は、普通のメソッド形式で書くと private string[] func(string line){ return line.Split('='); } と置き換えることができます。 置き換えた場合、 lines.Select(line => line.Split('=')); の部分は lines.Select(func); となります。 Selectの内部を簡略化すると、以下のような定義になっていて、内部のループで、渡された関数を使って値を変換しています。 ※簡略化した上で都合がいいのでforeachにしただけであって、実際にforeachが使われているわけではありません。 public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector){ foreach(var item in source){ yield return selector(item); } } 参考サイトです。 https://ufcpp.net/study/csharp/sp3_lambda.html
k_mail

2019/01/06 01:20 編集

select文の中で、1つずつ要素を処理するコードがあるんですね。。 (今思えば、SQLのSelectも一番上だけ取ってこないのと同じ感じでしょうか。) 参考サイト、一読しましたが、難しいので何度も読んで理解を深めたいと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問