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

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

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

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

Q&A

解決済

3回答

3319閲覧

クエリ構文をメソッド構文に変換する

Solalis345

総合スコア12

C#

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

0グッド

0クリップ

投稿2017/06/02 16:38

編集2017/06/02 16:44

###前提・実現したいこと
CSVファイルを読み込んで出力するLinqを作成しております。
クエリ構文では記述ができたのですが、
メソッド構文で記述する場合はどのようになるのでしょうか?

###該当のソースコード

var baseDirectory = new DirectoryInfo(@"C:"); IEnumerable<string> results = from path in baseDirectory.Flatten( directory => directory.GetDirectories(), directory => directory.GetFiles("*.csv")) from fields in CSVFiled.Context(path.FullName, ",", Encoding.GetEncoding(932)) select string.Format("〒{0} {1}{2}{3}", fields[2], fields[6], fields[7], fields[8]); //Flatten //public static IEnumerable<U> Flatten<T, U>(this T node, Func<T, IEnumerable<T>> predictBySubNode, Func<T, IEnumerable<U>> predictByNode) //ファイルのパスを返すイテレーター //CSVFiled.Context //public static IEnumerable<string[]> Context(string path, string separator = ",", Encoding encoding = null) //CSVファイルを読み込んでカンマ区切りの配列を返すイテレーター

###試したこと

下記で実行した場合、1行よくわからない文字列が出力されただけでした。 var results2 = baseDirectory.Flatten( directory => directory.GetDirectories(), directory => directory.GetFiles("*.csv")) .Select(path => CSVFiled.Context(path.FullName, ",", Encoding.GetEncoding(932))) .Select(fields => fields.Select(field => string.Format("〒{0} {1}{2}{3}", field[2], field[6], field[7], field[8])));

###補足情報(言語/FW/ツール等のバージョンなど)
C# 7.0

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

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

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

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

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

guest

回答3

0

連載:[完全版]究極のC#プログラミング Chapter16 LINQとメソッド構文
http://www.atmarkit.co.jp/fdotnet/extremecs/extremecs_16/extremecs_16_14.html
によると

クエリ構文で書いてから逆コンパイルすると
クエリ構文と等価なメソッド構文が出力されるようです。

投稿2017/06/03 21:13

AketiJyuuzou

総合スコア1147

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

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

Solalis345

2017/06/03 21:51

逆コンパイルという手段もあるんですね 惜しむらくは.NET Reflectorが有料な点ですね ありがとうございます。
guest

0

ベストアンサー

CSVFiled が不明で Flatten の実装が推測できませんが、こんな感じでしょうか?

C#

1var results = 2 baseDirectory.Flatten 3 ( 4 directory => directory.GetDirectories(), 5 directory => directory.GetFiles("*.csv") 6 ) 7 .SelectMany 8 ( 9 path => CSVFiled.Context(path.FullName, ",", Encoding.GetEncoding(932)), 10 (a, b) => string.Format("〒{0} {1}{2}{3}", b[2], b[6], b[7], b[8]) 11 );

投稿2017/06/03 01:26

編集2017/06/03 02:27
hihijiji

総合スコア4150

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

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

Solalis345

2017/06/03 21:55

ありがとうございます。 頂いたコードで試したところ想定通りの動作でした。ありがとうございます。 .Select().Select()と.SelectMany()は動作が異なるんですね。 .SelectMany()の動作について勉強します。
guest

0

うまく実行できるかを確認できてないですが、fieldsに対するSelectは余分のように思えます。以下のようにすべきでは?

.Select(path => ...)
.Select(fields => string.Format("〒{0} {1}{2}{3}", fields[2], fields[6], fields[7], fields[8])));

fieldsはString[]ですが、元のコードではfieldsに対してパイプライン処理(Select)を施しているのでfieldはStringになります。そのためfield[2]とかやると「文字列の3番目の文字」という意味になってしまいます。


訂正1:Contextの戻り値の型を勘違いしてました。ContextがIEnumerable<String[]>ならば以下のようにSelectManyを使うと素直に書けると思います。

...
.SelectMany(path => CSVFiled.Context(path.FullName, ",", Encoding.GetEncoding(932)))
.Select(fields => string.Format("〒{0} {1}{2}{3}", fields[2], fields[6], fields[7], fields[8])));

しかし、こう書いても質問者さんの書き方でも同じだと思うので原因がわからないです。


ちなみにもし質問者さんの書き方をするならfieldsという名前は不適切ではないでしょうか?
各行の集まり=>複数の行なのですからfieldsではなくrowsとでもいうべきだと思います。
rowsに対するパイプラインでrowsの各要素=row=fieldsと呼ぶべきかと。

...
.Select(path => CSVFiled.Context(path.FullName, ",", Encoding.GetEncoding(932)))
.Select(rows => rows.Select(fields => string.Format("...", fields[2], ...)));

投稿2017/06/03 00:37

編集2017/06/03 01:09
KSwordOfHaste

総合スコア18394

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

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

Solalis345

2017/06/03 00:51 編集

ご回答ありがとうございます。 .Select(fields => string.Format("〒{0} {1}{2}{3}", fields[2], fields[6], fields[7], fields[8])));の場合、 「角かっこ[] 付きインデックスを 'IEnumerable<string[]>' 型の式に適用することはできません」 とエラーが発生しました。 そのため、IEnumerable<string[]>の要素を抽出するのにSelectが必要だと思っていました。
KSwordOfHaste

2017/06/03 00:59

失礼しました。Contextの戻り値の解釈を間違えてました。
KSwordOfHaste

2017/06/03 01:11

ところで結果はIEnumerable<string>ですがそれをどのように表示されたのでしょう?
Solalis345

2017/06/03 21:57

返信遅れまして申し訳ありません。 表示されたのは次のような感じでした。 「System.Linq.Enumerable+WhereSelectEnumerableIterator`2[System.String[],System.String]」 .SelectManyを使用したら動作しましたので、SelectManyの動作について勉強してみます。 ありがとうございました。
KSwordOfHaste

2017/06/03 22:14

解決とのことで蛇足ですが > それをどのように表示されたのでしょう? は、「IEnumerable<string>の変数をそのままConsole.WriteLineなどとしても表示できないはずなので、どうやった確認されましたか?」と質問したつもりでしたw;
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問