teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

追記

2019/06/26 02:44

投稿

Zuishin
Zuishin

スコア28675

answer CHANGED
@@ -1,1 +1,97 @@
1
- 質問の本質がよくわかりませんが、マッピングクラスで Ignore を使うのはどうでしょうか?
1
+ 質問の本質がよくわかりませんが、マッピングクラスで Ignore を使うのはどうでしょうか?
2
+
3
+ # 追記
4
+
5
+ 質問を読み誤っていたようです。
6
+ 次のコードの DecodeCsv を使えば CSV を IEnumerable<IEnumerable<string>> に変換できます。これでLINQ を使用して特定のフィールドを読み飛ばし、使用するフィールドを変換するという手もあります。
7
+
8
+ ```C#
9
+ using System;
10
+ using System.Collections.Generic;
11
+ using System.Linq;
12
+ using System.Text.RegularExpressions;
13
+
14
+ namespace Zuishin
15
+ {
16
+ /// <summary>
17
+ /// CSV を解析または CSV に変換する
18
+ /// </summary>
19
+ public static class Csv
20
+ {
21
+ /// <summary>
22
+ /// CSV を解析する
23
+ /// </summary>
24
+ /// <param name="source">CSV の各行を保持する文字列の集合</param>
25
+ /// <returns>解析結果</returns>
26
+ public static IEnumerable<IEnumerable<string>> DecodeCsv(this IEnumerable<string> source)
27
+ {
28
+ const string contentName = "content";
29
+ Regex quoted = new Regex($"^\"(?<{contentName}>([^\"]|\"\")*)\"(,|$)");
30
+ Regex normal = new Regex($"^(?<{contentName}>[^,]*)(,|$)");
31
+ var enumerator = source.GetEnumerator();
32
+ while (enumerator.MoveNext())
33
+ {
34
+ var record = new List<string>();
35
+ string line = enumerator.Current;
36
+ while (!string.IsNullOrEmpty(line))
37
+ {
38
+ Match match;
39
+ if (line[0] == '"')
40
+ {
41
+ do
42
+ {
43
+ match = quoted.Match(line);
44
+ if (match.Success)
45
+ {
46
+ var content = match.Groups[contentName];
47
+ record.Add(content.Value.Replace("\"\"", "\""));
48
+ line = line.Substring(match.Length);
49
+ break;
50
+ }
51
+ if (!enumerator.MoveNext())
52
+ {
53
+ record.Add(line);
54
+ line = "";
55
+ break;
56
+ }
57
+ line += "\n" + enumerator.Current;
58
+ } while (true);
59
+ }
60
+ else
61
+ {
62
+ match = normal.Match(line);
63
+ record.Add(match.Groups[contentName].Value);
64
+ line = line.Substring(match.Length);
65
+ }
66
+ }
67
+ yield return record;
68
+ }
69
+ }
70
+
71
+ /// <summary>
72
+ /// CSV を作る
73
+ /// </summary>
74
+ /// <param name="source">元となる集合</param>
75
+ /// <param name="alwaysQuote">true ならば各フィールドをダブルクォーテーションで囲む</param>
76
+ /// <returns>CSV</returns>
77
+ public static IEnumerable<string> EncodeCsv(this IEnumerable<IEnumerable<string>> source, bool alwaysQuote = false)
78
+ {
79
+ var regex = new Regex("^\"|[,\n]");
80
+ string quote(string s)
81
+ {
82
+ return $"\"{s.Replace("\"", "\"\"")}\"";
83
+ }
84
+ string quoteIfNeeded(string s)
85
+ {
86
+ if (regex.IsMatch(s)) return quote(s);
87
+ return s;
88
+ }
89
+ var translate = alwaysQuote ? (Func<string, string>)(a => quote(a)) : a => quoteIfNeeded(a);
90
+ foreach (var record in source)
91
+ {
92
+ yield return string.Join(",", record.Select(translate));
93
+ }
94
+ }
95
+ }
96
+ }
97
+ ```