やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

TSVをHTMLのtableに変換する(python)

 とりあえず簡易的に作ってみた。

成果物

 TSVから以下のようなテーブルが作れる。他にもたくさんのパターンがある。詳細はdemo参照。

ABC
abcde
AaABCDEFG
bHIJKLMN
BcOPQXRSTZaU
dVWYb
cdefghi
ejklmnop
Cqrstuvw

 入力したTSVは以下。

 Excel, Calcなどの表計算ソフトでセル結合し、それをコピーしてテキストエディタにペーストしたときの値である。

使い方

git clone https://github.com/ytyaru/Python.Tsv2HtmlTable.20201022074246
cd Python.Tsv2HtmlTable.20201022074246
cat ./docs/tsv/matrix_3.tsv | ./src/tsv2table.py

コマンド引数

tsv2table.py [-H a|r|c|m] [-r t|b|B] [-c l|r|B]
初期値候補値
-H--headera
aautoヘッダを推測する。
1行目1列目が空でなければ列ヘッダなし。
1行目に空がなければ行ヘッダは1行のみ。
rrow行ヘッダがある。
ccolumn列ヘッダがある。
mmatrix行列ヘッダがある。
-r--rowt
ttop行ヘッダを上端に配置する。
bbottom行ヘッダを下端に配置する。
Bboth行ヘッダを上下両端に配置する。
-c--columnl
lleft列ヘッダを左端に配置する。
rright列ヘッダを右端に配置する。
Bboth列ヘッダを左右両端に配置する。

できるようになったこと

  • ヘッダの階層表現
    • ヘッダを複数行・列にする
    • ヘッダをセル結合する
  • ヘッダ位置を変える
    • 下、右

できないこと

  • ヘッダをセル結合しないフラグ
    • 結合せず空のままにする。だがそんな要件はないと断定して実装しない
  • データをセル結合するフラグ
    • どう結合すればいいか判断できないため実装不能

データセルは結合できない

 どう結合すればいいか判断できないため実装不能

 たとえば下の表をみてみる。データセルOPがある。その右隣が空セルである。一見、その2セルが結合するようにみえる。だが、上にあるIと空セルが結合すべきかもしれない。果たしてどちらと結合するものと判断すればいいのか不明。

ABC
abcde
AaABCDEFG
bHIJKLMN
BcOPQXRSTZaU
dVWYb
cdefghi
ejklmnop
Cqrstuvw

 AsciiDocのように軽量マークアップ言語を開発する方法もある。だがそれでいいならAsciiDocを使えばいい。そもそも、あれもHTMLと大差ない複雑さである。

 このツールはTSVでサクっと表を作れるのがウリ。だからこのツールでは、ヘッダの包含関係を表すときのみセル結合する。そういう表しか作れない仕様にする。これによりTSVだけでセル結合したHTMLの表が作れるようになる。TSV、コマンド引数以外にcolspan, rowspan属性を指示する必要がない。

列ヘッダのみの表は-H c引数を省略できない

 このツールはできるだけ引数を指定せずに様々なパターンの表を作ることが目標である。だが、列ヘッダのみある表の場合、-H c引数を省略できない。なぜなら行ヘッダのみの表と区別をつけられないから。

 少なくともどちらか一方はデフォルト値にして省略できる。このツールは行ヘッダのみのパターンまたは行列両方あるパターンがデフォルトである。なぜならHTMLのtableタグは行ヘッダが仕様だから。むしろ本来、列ヘッダのみの表は想定外と思われる。<thead>,<tr>のタグをみれば行指向なのは明らか。よって、行ヘッダのみの表をデフォルトとする。結果、列ヘッダのみの表は-H c引数を指定せねばならない。

課題

  • TSVにコマンド引数を書いて読み取る
    • #! tsv2table.py -H c
      • これで列ヘッダのみの表でもコマンド実行時にTSVを渡すだけでよくなる(引数省略)
      • ただ、表現方法については要検討
        • TSVにシバンとかおかしい
        • そもそもシバンに引数を渡すことはできない
        • そもそもファイルの内容はデータであって実行する命令文でない
        • https://unix.stackexchange.com/questions/399690/multiple-arguments-in-shebang#answer-477651
          • #!/usr/bin/env -S Command arg1 arg2 ...
          • TSVの1行目にシバン + chmod x a.tsv + ./a.tsv
          • #!/usr/bin/env -S /tmp/work/CSharp.TsvToHtmlTable.20201028082641/bin/tsv2table -- -H r ${BASH_SOURCE}
          • これで実行できた! ${BASH_SOURCE}の代わりに${0}は使えなかった……
          • C# CommandLineParserに渡すためには引数を配列にせねばならない。そのためのパーサを書かねばならない……。
    • #コメント
  • 出力パターン
    • 以下、python多態性が表現できずDRYに書けないため断念(C#での実装を検討)
    • ヘッダなし
    • ヘッダ内包パターン
      • 奇数列の全行がヘッダである
      • 偶数列の全行がヘッダである
      • 奇数行の全列がヘッダである
      • 偶数行の全列がヘッダである
      • 指定開始列から指定ステップ列数ごとの列が全行ヘッダである
      • 指定開始列から指定ステップ行数ごとの行が全列ヘッダである

所感

 課題を実装しようとするとpythonでは厳しい。アルゴリズムの実装に多態性を使いたいが、pythonでは使えないから。よってC#で実装したい。

他言語に浮気しまくる理由

私はMr.コンパイラじゃない。凡人だから。  スクリプト言語だとサクっと書けていいよね。書き始めるのだが……。

  1. やりたいことが増えると複雑化する
  2. スクリプト言語だと限界を迎える(言語仕様: bash:二次元配列使えず, python:多態性使えず)
  3. 高級プログラミング言語で作り直す

 なら最初から大規模に耐えうる言語で書いたほうが良かったよね……。でもどの言語がどれくらいの規模に耐えられるかを判断するのは難しい。以下を予測せねばならないから。

  1. この案件はどのくらいの規模になるのか?
  2. どの言語はどのくらいの規模の案件に使うべきか?

 そして上記を予測するのは極めて難しい。コードを書く前に設計すれば予測できる。だが、設計するには最低でも各言語の言語仕様を把握していねばならない。私のように書きながら言語学習も同時にしているレベルの人間にはムリ。

 じつは言語仕様どころか、要件すらも洗い出しきれていなかった。細かいことは実際にコードを書いて動かさないと気づけない。たとえばデータセル結合とか。コードを書く前は漠然とできると思っていた。書いてて「あれ、できなくね?」と気づく有様。

 つまり私が未熟だから浮気することになる。

書き直しまくる原因

 そもそも他言語に浮気することは問題の本質ではない。

 問題は書き直しまくるハメになることだ。そしてその原因は以下。

  • アルゴリズムを事前に考えられないから仕様を事前に詰めきれない
  • 言語仕様に沿ったデザインパターンで設計できない。言語仕様を把握しきれていないから

 でもこれ、凡人にはできなくて当然では?

 だから凡人には「サクっと動くものを書くことで曖昧になりがちなものを明確化する」という作業が必要だと思う。少なくとも多少は仕方ないのでは? 脳内コンパイラを持っていない限り省けない。もう必要な工程だと割り切るしかないよね?

 それとも以下をすべて身につけろと? ムリ。できたら人間じゃないわ。Mr.コンパイラの称号をくれてやろう。

 はいムリ。だから書かなきゃならなかった。

問題ない

 そう、私は無駄なことなんてやってないんだ!

 これは中途半端な成果物なんかじゃない。これが仕様で、ここまでできる成果物なんだ! 「現状が仕様です」なのだ! たとえその仕様を突き詰めることができていなくったってコードがあればコードが仕様なんだぁあああ! コードに逆らう奴、それこそが悪! コードが答えであり神なんだッ!

 いやまて落ち着け。逃げるな。俺の追求力はこんなもんじゃねぇはずだ。諦めるな。戦え。そうだ、C#で書こう。とことん理想を追求した究極極限極大最強ツールを。

 これは浮気じゃない。新たなステージへと駆け上るサクセスストーリーなのだ。羽ばたく俺様の美技に酔いな!

 人間コンパイラになれないって? それがどうした! 熱く煮えたぎるこの想いがコードを書き出す原動力なんだよ! コンパイラにコードは書けない。人がコードを書くんだ! 俺の導きで世界は解き放たれる。

 人より劣っている? うるせぇ! 俺がやるったらやるんだよ! 優れてなきゃコード書いちゃダメなのか? クソコードを拡散するなと? よーしその喧嘩、買った。クソコードを量産しまくってやる! ざまぁみろ!

 書き直しまくることが問題だって? バカめ。コードを書くことが目的なんだよ! 出来高なんて知ったことか! 俺、コードたくさん書く。俺、シアワセ。これでいいのだ!

 それをムダとか問題だと思うことが問題だ。なぜそれをシアワセと思えない? 

 ムダとは遊びであり豊かさそのもの。味わい堪能することで人生を謳歌できる。問題とはこの手で解決に変化させられる。その瞬間の快楽たるや他の何物にも代えがたい。

 何かをムダと思うサモシイ心こそがムダ。そんな価値観こそが悪! 楽しめなくなっちゃ終わりだぜ。それを楽しいと思えばオールオッケー。コードを書きまくれて俺は楽しい。ならば……

 問題なんてどこにもなかったんや!

今回のコード

 汚い。もっとキレイに書けなかったものか。私にはこれが限界。未熟。

 機能が半端だからPyPIにアップロードすべきとも思えない。

 まずはC#で全要件を載せたコードをキレイに書きたい。ちゃんとするのはそれからってことで。そこまで辿り着けるかな?

対象環境

$ uname -a
Linux raspberrypi 5.4.51-v7l+ #1333 SMP Mon Aug 10 16:51:40 BST 2020 armv7l GNU/Linux