回答編集履歴

1

追記

2019/06/26 02:44

投稿

Zuishin
Zuishin

スコア28660

test CHANGED
@@ -1 +1,193 @@
1
1
  質問の本質がよくわかりませんが、マッピングクラスで Ignore を使うのはどうでしょうか?
2
+
3
+
4
+
5
+ # 追記
6
+
7
+
8
+
9
+ 質問を読み誤っていたようです。
10
+
11
+ 次のコードの DecodeCsv を使えば CSV を IEnumerable<IEnumerable<string>> に変換できます。これでLINQ を使用して特定のフィールドを読み飛ばし、使用するフィールドを変換するという手もあります。
12
+
13
+
14
+
15
+ ```C#
16
+
17
+ using System;
18
+
19
+ using System.Collections.Generic;
20
+
21
+ using System.Linq;
22
+
23
+ using System.Text.RegularExpressions;
24
+
25
+
26
+
27
+ namespace Zuishin
28
+
29
+ {
30
+
31
+ /// <summary>
32
+
33
+ /// CSV を解析または CSV に変換する
34
+
35
+ /// </summary>
36
+
37
+ public static class Csv
38
+
39
+ {
40
+
41
+ /// <summary>
42
+
43
+ /// CSV を解析する
44
+
45
+ /// </summary>
46
+
47
+ /// <param name="source">CSV の各行を保持する文字列の集合</param>
48
+
49
+ /// <returns>解析結果</returns>
50
+
51
+ public static IEnumerable<IEnumerable<string>> DecodeCsv(this IEnumerable<string> source)
52
+
53
+ {
54
+
55
+ const string contentName = "content";
56
+
57
+ Regex quoted = new Regex($"^\"(?<{contentName}>([^\"]|\"\")*)\"(,|$)");
58
+
59
+ Regex normal = new Regex($"^(?<{contentName}>[^,]*)(,|$)");
60
+
61
+ var enumerator = source.GetEnumerator();
62
+
63
+ while (enumerator.MoveNext())
64
+
65
+ {
66
+
67
+ var record = new List<string>();
68
+
69
+ string line = enumerator.Current;
70
+
71
+ while (!string.IsNullOrEmpty(line))
72
+
73
+ {
74
+
75
+ Match match;
76
+
77
+ if (line[0] == '"')
78
+
79
+ {
80
+
81
+ do
82
+
83
+ {
84
+
85
+ match = quoted.Match(line);
86
+
87
+ if (match.Success)
88
+
89
+ {
90
+
91
+ var content = match.Groups[contentName];
92
+
93
+ record.Add(content.Value.Replace("\"\"", "\""));
94
+
95
+ line = line.Substring(match.Length);
96
+
97
+ break;
98
+
99
+ }
100
+
101
+ if (!enumerator.MoveNext())
102
+
103
+ {
104
+
105
+ record.Add(line);
106
+
107
+ line = "";
108
+
109
+ break;
110
+
111
+ }
112
+
113
+ line += "\n" + enumerator.Current;
114
+
115
+ } while (true);
116
+
117
+ }
118
+
119
+ else
120
+
121
+ {
122
+
123
+ match = normal.Match(line);
124
+
125
+ record.Add(match.Groups[contentName].Value);
126
+
127
+ line = line.Substring(match.Length);
128
+
129
+ }
130
+
131
+ }
132
+
133
+ yield return record;
134
+
135
+ }
136
+
137
+ }
138
+
139
+
140
+
141
+ /// <summary>
142
+
143
+ /// CSV を作る
144
+
145
+ /// </summary>
146
+
147
+ /// <param name="source">元となる集合</param>
148
+
149
+ /// <param name="alwaysQuote">true ならば各フィールドをダブルクォーテーションで囲む</param>
150
+
151
+ /// <returns>CSV</returns>
152
+
153
+ public static IEnumerable<string> EncodeCsv(this IEnumerable<IEnumerable<string>> source, bool alwaysQuote = false)
154
+
155
+ {
156
+
157
+ var regex = new Regex("^\"|[,\n]");
158
+
159
+ string quote(string s)
160
+
161
+ {
162
+
163
+ return $"\"{s.Replace("\"", "\"\"")}\"";
164
+
165
+ }
166
+
167
+ string quoteIfNeeded(string s)
168
+
169
+ {
170
+
171
+ if (regex.IsMatch(s)) return quote(s);
172
+
173
+ return s;
174
+
175
+ }
176
+
177
+ var translate = alwaysQuote ? (Func<string, string>)(a => quote(a)) : a => quoteIfNeeded(a);
178
+
179
+ foreach (var record in source)
180
+
181
+ {
182
+
183
+ yield return string.Join(",", record.Select(translate));
184
+
185
+ }
186
+
187
+ }
188
+
189
+ }
190
+
191
+ }
192
+
193
+ ```