PythonでCSVのFixtureをYAMLに変換(添削希望・・・)などと書いていたんですが、なんとid:perezvonさんが添削してくださいました!
あざーっす!
元のコード:
import sys
import csv
if (len(sys.argv) < 2):
print 'Usage: %s ' % sys.argv[0]
quit()
csv_file = sys.argv[1]
filename, suffix = csv_file.split('.')
reader = csv.reader(file(csv_file, 'r'))
i = -1
res = []
for row in reader:
i += 1
if i == 0:
column = row
continue
s = filename + str(i) + ":\n"
for j in range(len(column)):
s += " " + column[j] + ": " + row[j] + "\n"
res.append(s)
f = open(filename + ".yml", 'w')
f.write("\n".join(res))
f.close()
添削していただいたコード:
import sys
import csv
import yaml
def main(src, dest):
reader = csv.reader(file(src))
data = list(reader)
result = []
cols = data[0]
rows = data[1:]
for row in rows:
result.append(dict([(k, v) for k, v in zip(cols, row)]))
yaml.safe_dump(result, file(dest, 'wb'),
default_flow_style=False,
encoding='utf-8',
allow_unicode=True)
if __name__ == '__main__':
if len(sys.argv) < 2:
print 'Usage: %s [filename]' % sys.argv[0]
sys.exit(1)
src = sys.argv[1]
dest = src.replace('.csv', '.yml', src.rindex('.'))
main(src, dest)
ジーザス・・・スマート!
こちらを参考に復習していきたいと思います。
まずこの部分。
if __name__ == '__main__'
なるほど〜Rubyでもやりますね。この辺は無意識にできるようになりたい。
rows = data[1:]
csvの1行目以降を簡単に取っている。どうも簡単なデータ構造を基本的な処理の組み合わせでシンプルに扱うというところを疎かにしがちで冗長になったり、安易にクラスにしたりするので反省していきたい。
そしてこのコードの処理の大半が次の一行に凝縮されている。
result.append(dict([(k, v) for k, v in zip(cols, row)])
zip関数を使うと複数のシーケンスを簡単に回せるんですね!これ、Rubyだとちょっと面倒な処理だと思います。(俺のRubyスキルの低さ含めて)
これはモテる!
yaml.safe_dump
そしてyaml.safe_dump。まさに元エントリーで書かれているように、普通にyaml.dumpして(´・ω・`)となっていました・・・。
dest = src.replace('.csv', '.yml', src.rindex('.'))
ここも素敵。元のコードだとピリオドが一つ以上あるファイル名でおかしなことになりますね。
同じ問題をうまい人にも解いてもらってそれを見るのはとても勉強になりますね。プログラマの教育の話でも目の前で解いて見せるという話がありましたが、とても効率的な気がしました。
日々ブログに恥を垂れ流してますが時々こういう良い事があるので嬉しいですね。ありがとうございます!