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

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

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

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

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

1回答

1790閲覧

テーブルのレコードを配列にしたい

takagi.1994

総合スコア47

C#

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

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

0グッド

0クリップ

投稿2017/03/29 17:47

編集2017/03/30 02:21
<div> <table border="1" cellpadding="5" cellspacing="0" width="100%" class="list"> <tr> <th rowspan="2">country</th> <th rowspan="2">class<div></div><div></div></th> <th rowspan="2">date</th> <th rowspan="2">no</th> <th rowspan="2">value</th> <th rowspan="2"><div>volume</div><div></div></th> <th rowspan="2">evaluation</th> <th rowspan="2">total</th> <th colspan="2">a</th> </tr> <tr> <th>b</th> <th>c</th> </tr> <tr> <td rowspan="4">JAPAN</td> <td rowspan="2">class1</td> <td> <div>2017/03/29</div> <div>15:36:12</div> </td> <td>10011879</td> <td>18.5121</td> <td><div>1</div><div></div></td> <td><div></div></td> <td><div></div></td> <td>a</td> <td rowspan="2">b</td> </tr> <tr> <td> <div>2017/03/30</div> <div>01:16:01</div> </td> <td>1092115019</td> <td>18.5237</td> <td><div>1</div><div></div></td> <td><div></div></td> <td><div></div></td> <td>c</td> </tr> <tr> <td rowspan="2">class2</td> <td> <div>2017/03/29</div> <div>15:36:24</div> </td> <td>100001894</td> <td>18.5028</td> <td><div>1</div><div></div></td> <td><div></div></td> <td><div></div></td> <td >a</td> <td rowspan="2">c</td> </tr> <tr> <td> <div>2017/03/30</div> <div>01:15:53</div> </td> <td>2115002</td> <td>18.5136</td> <td><div>1</div><div></div></td> <td><div></div></td> <td><div></div></td> <td>b</td> </tr> <tr> <td rowspan="4">HONGKONG</td> <td rowspan="2">class1</td> <td> <div>2017/03/30</div> <div>01:15:47</div> </td> <td>1014990</td> <td>17.3090</td> <td><div>1</div><div></div></td> <td><div></div></td> <td><div></div></td> <td>a</td> <td rowspan="2" >c</td> </tr> <tr> <td> <div>2017/03/29</div> <div>15:36:38</div> </td> <td>1020</td> <td>17.3270</td> <td><div>1</div><div></div></td> <td><div></div></td> <td><div></div></td> <td>b</td> </tr> <tr> <td rowspan="2">class2</td> <td> <div>2017/03/30</div> <div>01:15:35</div> </td> <td>14980</td> <td>17.2909</td> <td><div>1</div><div></div></td> <td><div></div></td> <td><div></div></td> <td>a</td> <td rowspan="2">c</td> </tr> <tr> <td> <div>2017/03/29</div> <div>15:36:47</div> </td> <td>1031</td> <td>17.3083</td> <td><div>1</div><div></div></td> <td><div></div></td> <td><div></div></td> <td>b</td> </tr> </table> </div> </div>

このようなテーブルから正規表現にて各レコードをListにしたいのですが、どうしたらよいでしょうか?

List<List<string>> JAPAN = new List<List<string>>(); JAPAN.Add(new List<string>() { class, date, no, value }); List<List<string>> HONGKONG= new List<List<string>>(); HONGKONG.Add(new List<string>() { class, date, no, value });

country別のListにしたいと考えています。

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

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

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

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

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

Zuishin

2017/03/29 23:29

なぜ正規表現なのですか? DOM や LINQ for XML ではダメなのですか? そのデータは人間が打ち込んだものですか? それとも自動生成されたものですか? 自分で作ったものですか? それとも自分では変更できないものですか?
ku__ra__ge

2017/03/30 01:17 編集

コードをそのまま質問文に書くと整形が崩れますし、どこまでがコードなのか一目で分かり辛いです。コード前後に『```』という行を入れるように修正してください。
takagi.1994

2017/03/30 02:28

正規表現の理由は現在正規表現で処理していてソース側の変更があったため。また、その他の手段に関しては検討します。今回は自分の正規表現のスキルアップも含め、正規表現で効率のよい書き方とはどういう書き方があるのか多くの方がどのような考え方でされているか参考にしたかったためです。
Zuishin

2017/03/30 02:43

今、質問に上がっているものから正規表現でデータを取り出すことはできます。しかし、人間が打ち込むものであれば、必ずしも正しいデータとは限らず、今後その正規表現が使えなくなる可能性があります。他者た作ったものなら猶更いつ変更されるものかはわかりません。だから、これら私からの質問は、質問者さんが自ら質問として挙げなけらばならなかった重要な情報です。この回答はここでなく、質問を編集してください。
takagi.1994

2017/03/30 03:13

今後使えなくなるとかそこは今回の件では問題ではありません。今、このテーブルに対しての正規表現を使ってという目的を達成するためにはどうするかが知りたいのであって、今後変更があるかもとかそのようなことは今回の質問には関係ないことなので書きませんでした。
Zuishin

2017/03/30 03:29

関係ないかどうかは回答者はわかりません。プログラミングするときにはそこまで考えて汎用性をどの程度とるかを決めますので、はっきり書かなければなりません。たとえば、まったく変更がないのであれば、正規表現を使うまでもなく、この元々のデータを破棄してコンバート済みのデータをもっと扱いやすい形で保存するのが最善です。
Zuishin

2017/03/30 03:50 編集

今回の場合、rowspan の扱いがややこしいので、通常であれば、三段階踏むのが易しいと思います。つまり、country で一段階、class と c で一段階、date から b までで一段階です。しかしそれはデータが変更されるという前提です。変更されないのならば、各 class の要素は 2、各国の要素は 4 と決まっているので、決め打ちで一段階でできます。難易度が全然変わります。
takagi.1994

2017/03/30 04:53 編集

関係ないことまで書いて論点がずれてはこまるので質問に対しての答えをとおもい、あえてこのような質問をしたつもりでしたが、逆に難しくしたのであれば申し訳ありません。実際にはテーブルの仕様としては変更ありませんが、date以降のレコードが増えたり減ったりします。そういった意味で不変ではありません。
Zuishin

2017/03/30 04:49

どんな変更があり得ますか?
Zuishin

2017/03/30 04:50

また、data とは何を指しますか?
takagi.1994

2017/03/30 04:54

すいません、誤字です。dataではなくdateです。わかりやすくいえば大項目countyの中項目classで分けられたレコードが状況によって増減します。
Zuishin

2017/03/30 05:01

つまり、二か国固定、class も二つ固定、class 内のレコード数は不定で最低 0 ということですか?
Zuishin

2017/03/30 05:45

0? 最低 1 ではありませんか?
takagi.1994

2017/03/30 05:52

date以降のレコードは0の場合もありえます
Zuishin

2017/03/30 05:57

フィールドではなくレコードですね?
takagi.1994

2017/03/30 06:01

常にjapanとclass1があるから0はなりえないとおっしゃりたいのであればその通りです。私は、date以降のレコードはと書いているつもりです
takagi.1994

2017/03/30 06:02

こんかいの解決にそこまで細かい要件が必須なのでしょうか?
takagi.1994

2017/03/30 06:06

このように論点がずれることを恐れて、質問のテーブルに対して最も効率がよい正規表現という技術を身に着けたいと考えたまでで、それ以外の要因等は正規表現以外の要素も含んでくるのでスルーしていただきたかったのですが。
Zuishin

2017/03/30 06:10

フィールドとレコードの区別はついていますか? 論点は全くずれていません。仕様が決まらなければプログラムは組めません。必要な仕様がきちんと書かれていないのでこのように細かく聞かなければならない事態になっています。
takagi.1994

2017/03/30 06:17

date以降と書いていますが?仕様?最初に提示したテーブルといっています。聞かれたことに答えましたが聞かれた質問があげあしとりのようにしか感じません。明確に言っているつもりです。質問した際のテーブルと
takagi.1994

2017/03/30 06:19 編集

japanやclassはレコードかフィールドかを聞かれているのだと思いますが、その質問だとフィールドではありません。レコードです。
Zuishin

2017/03/30 06:22

違います。フィールドです。
Zuishin

2017/03/30 06:24

一応、フィールド固定レコード可変で正規表現を載せましたので、参考になるならどうぞ。
takagi.1994

2017/03/30 06:49

レコードですけど?いいだしたらキリがありませんが、実態はcountryもclassも複数あります。テーブルの仕様上の問題なだけです
Zuishin

2017/03/30 06:55

いいえ、フィールドです。Japan, Hongkong ならレコードですが、Japan, Class1 はフィールドの列挙です。date もフィールドです。用語が怪しいと仕様は伝わりません。
takagi.1994

2017/03/30 07:11

>フィールドではなくレコードですね?こうあったので認識にズレがあったとおもいますが、私はあくまでレコード単位で話をしていましたjapan単体というとまた語弊があるかもしれませんが、それだけをフォーカスしてフィールドとはという投げかけとは解釈ていおりませんでした。
Zuishin

2017/03/30 07:13

date 以降という言葉があったので用語を確認しました。date はフィールドの名前であってレコードではありません。今も少し怪しい感じですので、もう一度用語を確認してください。
Zuishin

2017/03/30 07:16

訂正。date はカラムの名前です。
takagi.1994

2017/03/30 07:20

日本語って難しいですね。それもまたそういう意味で書いたつもりではないのです。
guest

回答1

0

正規表現だけ欲しいのであれば、こうです。

C#

1var cls = @"<td\s+rowspan=""(?<classLength>\d+)"">(?<class>[^<]+)</td>\s*"; 2var country = @"<td\s+rowspan=""(?<countryLength>\d+)"">(?<country>[^<]+)</td>\s*" + cls; 3var header =string.Format(@"(?:{0}|{1}|\s*)", country, cls); 4var dateTime = @"<td>\s*<div>(?<date>[^<]*)</div>\s*<div>(?<time>[^<]*)</div>\s*</td>\s*"; 5var no = @"<td>(?<no>[^<]*)</td>\s*"; 6var value = @"<td>(?<value>[^<]*)</td>\s*"; 7var volume = @"<td>\s*<div>(?<volume>[^<]*)</div>\s*<div></div>\s*</td>\s*"; 8var evaluation = @"<td><div>(?<evaluation>[^<]*)</div></td>\s*"; 9var total = @"<td><div>(?<total>[^<]*)</div></td>\s*"; 10var b = @"<td>(?<b>[^<]*)</td>\s*"; 11var regex = new Regex(header + dateTime + no + value + volume + evaluation + total + b, RegexOptions.Multiline); 12

現在与えられたデータを解析する仕様は満たしていますが、これでいいのですか?

参考までにデータはこうなります。

C#

1var cls = @"<td\s+rowspan=""(?<classLength>\d+)"">(?<class>[^<]+)</td>\s*"; 2var country = @"<td\s+rowspan=""(?<countryLength>\d+)"">(?<country>[^<]+)</td>\s*" + cls; 3var header =string.Format(@"(?:{0}|{1}|\s*)", country, cls); 4var dateTime = @"<td>\s*<div>(?<date>[^<]*)</div>\s*<div>(?<time>[^<]*)</div>\s*</td>\s*"; 5var no = @"<td>(?<no>[^<]*)</td>\s*"; 6var value = @"<td>(?<value>[^<]*)</td>\s*"; 7var volume = @"<td>\s*<div>(?<volume>[^<]*)</div>\s*<div></div>\s*</td>\s*"; 8var evaluation = @"<td><div>(?<evaluation>[^<]*)</div></td>\s*"; 9var total = @"<td><div>(?<total>[^<]*)</div></td>\s*"; 10var b = @"<td>(?<b>[^<]*)</td>\s*"; 11var regex = new Regex(header + dateTime + no + value + volume + evaluation + total + b, RegexOptions.Multiline); 12var items = regex 13 .Matches(src) 14 .OfType<Match>() 15 .Select(a => new 16 { 17 country = a.Groups["country"].Value, 18 countryLength = a.Groups["countryLength"].Value, 19 cls = a.Groups["class"].Value, 20 classLength = a.Groups["classLength"].Value, 21 date = a.Groups["date"].Value, 22 time = a.Groups["time"].Value, 23 no = a.Groups["no"].Value, 24 value = a.Groups["value"].Value, 25 volume = a.Groups["volume"].Value, 26 evaluation = a.Groups["evaluation"].Value, 27 total = a.Groups["total"].Value, 28 b = a.Groups["b"].Value 29 }); 30foreach (var item in items) 31{ 32 Console.WriteLine(string.Format( 33 "country:{8}\ncountryLength:{9}\nclass:{10}\nclassLength:{11}\ndate:{0}\ntime:{1}\nno:{2}\nvalue:{3}\nvolume:{4}\nevaluation:{5}\ntotal:{6}\nb:{7}\n\n", 34 item.date, 35 item.time, 36 item.no, 37 item.value, 38 item.volume, 39 item.evaluation, 40 item.total, 41 item.b, 42 item.country, 43 item.countryLength, 44 item.cls, 45 item.classLength 46 )); 47}

出力

country:JAPAN countryLength:4 class:class1 classLength:2 date:2017/03/29 time:15:36:12 no:10011879 value:18.5121 volume:1 evaluation: total: b:a country: countryLength: class: classLength: date:2017/03/30 time:01:16:01 no:1092115019 value:18.5237 volume:1 evaluation: total: b:c country: countryLength: class:class2 classLength:2 date:2017/03/29 time:15:36:24 no:100001894 value:18.5028 volume:1 evaluation: total: b:a country: countryLength: class: classLength: date:2017/03/30 time:01:15:53 no:2115002 value:18.5136 volume:1 evaluation: total: b:b country:HONGKONG countryLength:4 class:class1 classLength:2 date:2017/03/30 time:01:15:47 no:1014990 value:17.3090 volume:1 evaluation: total: b:a country: countryLength: class: classLength: date:2017/03/29 time:15:36:38 no:1020 value:17.3270 volume:1 evaluation: total: b:b country: countryLength: class:class2 classLength:2 date:2017/03/30 time:01:15:35 no:14980 value:17.2909 volume:1 evaluation: total: b:a country: countryLength: class: classLength: date:2017/03/29 time:15:36:47 no:1031 value:17.3083 volume:1 evaluation: total: b:b

投稿2017/03/30 06:12

編集2017/03/30 06:35
Zuishin

総合スコア28660

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

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

Zuishin

2017/03/30 06:15

実際使う場合には country countryLength class classLength を使って Select() で国とクラスを設定することになるでしょう。
takagi.1994

2017/03/30 06:41

ありがとうございます。 私はただ、正規表現が苦手なので思想を含め書き方の勉強をしたかったのです。 簡単なマッチや置換はできるのですが、このような入れ込んだテーブルの中から目的のセルの値を得るためのロジックがスマートにできないため参考にしたかったまでです。仕様や条件が変わるなどの問題は発生するかしないかわからない状況では優先順位が低かったためスルーでよかったのです。まだ提示いただいたものを読み込んではいないのですが、非常に参考になる回答だとおもいます。
Zuishin

2017/03/30 06:56

書き方の練習ならもっと単純なものから始めたらいいと思います。今回の問題は、よく正規表現を書いている者にとっても歯ごたえがあるもので、学習には向きません。
takagi.1994

2017/03/30 07:17

正規表現をよく書かれてる方がそうおっしゃるのであれば、苦手意識がある私にスマートな書き方ができないのは当然だとおもいます。歯ごたえがあったソースを読めて感謝です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問