enumerate()がPython風
先日書いていたCSVをJSONに変換するプログラムでfor文を使う際に
for i in range(len(LIST))
という書き方を多用していましたが、リストのインデックスを使って処理をしたい場合enumerate()を使うのがPythonらしい書き方のようです。
a = [0,1,2,3,4] for i,v in enumerate(a): print str(i) + " = " + str(v)
これを実行すると
0 = 0 1 = 1 2 = 2 3 = 3 4 = 4
と、なります。
これを利用して先日のCSV、JSON変換プログラムを書きなおしたのが以下です。
# coding: shift_jis #CSVを読み込んでJSON化する import sys import json import codecs from collections import OrderedDict if sys.argv[1][-4:] != ".csv": csvFileName = sys.argv[1] + ".csv" else: csvFileName = sys.argv[1] #読み出しで開く csvFile = open(csvFileName,'r') #行のリストを作成 eachLine = [] for line in csvFile: eachLine.append(line.replace("\n","").replace('\"','').replace("\'","")) #ファイル閉じる csvFile.close() eachPart = [""] * len(eachLine) #各行をカンマで分割 for i , v in enumerate(eachLine): eachPart[i] = v.split(',') #キーのリスト keyList = eachPart.pop(0) #dictのリストを作る eachDict = [""] * len(eachPart) for i , v in enumerate(eachPart): eachDict[i] = OrderedDict() if len(keyList) != len(eachPart[i]): print "Item #" + str(i) + " length adjust" #キーの長さより要素数が少ない場合は""で埋める(※1) if len(keyList) > len(eachPart[i]): gap = len(keyList) - len(eachPart[i]) eachPart[i].extend(gap * [""]) for j , vj in enumerate(keyList): eachDict[i][vj] = unicode((eachPart[i][j]) , "shift_jis") #(※2) #書きこむファイル作製 jsonFileName = csvFileName.replace('.csv','.json') jsonFile = codecs.open(jsonFileName,"w","utf-8") #JSON出力 json.dump(eachDict, jsonFile, ensure_ascii=False) #JSONファイル閉じる jsonFile.close()
enumerate()を使うとインデックスと値と2つの変数を使ってループすることになるので上の(※2)の部分ようにループ内でさらにループをする多重ループになるとかなり複雑になってしまいますね・・・。おそらくもっとうまい書き方があるんだと思います。
昨日と一昨日のエントリでIndex Errorを扱う方法を考えていたのは上のコードの「キーの長さより要素数が少ない場合は""で埋める(※1)」と書いている部分を""で事前に埋めるのではなく代入を試みて値がなければ埋めるというようにしたかったからなのですがうまい方法が見つからなかったので事前に埋めるようにしてみました。