風柳メモ

ソフトウェア・プログラミング関連の覚書が中心

【覚書】リスト(list)→辞書(dict)変換

2つのリストから、1つ目をキー、2つ目を値とする辞書を作成

def two_list_to_dict(key_list, val_list):
  return dict(zip(key_list, val_list))

print two_list_to_dict(['a','b','c'],[1,2,3]) # {'a': 1, 'c': 3, 'b': 2}

1つのリストから、キーを要素番号とする辞書を作成

def list_to_dict(val_list):
  #return two_list_to_dict(range(0,len(val_list)), val_list)
  return dict(zip(range(0,len(val_list)), val_list))

print list_to_dict(['a','b','c']) # {0: 'a', 1: 'b', 2: 'c'}

[key0,val0,key1,val1,...]となっているリストから、辞書を作成

参照

リストからディクショナリへの変換の最適化にみる賢明な Python プログラミング - forest book

def pairwise(iterable):
  itnext = iter(iterable).next
  while True:
    yield itnext(), itnext()

def key_val_list_to_dict(key_val_list):
  return dict(pairwise(key_val_list))

print key_val_list_to_dict(['a',1,'b',2,'c',3]) #{'a': 1, 'c': 3, 'b': 2}


ジェネレータ(generator)生成用関数について

yieldを含む関数をコールするとジェネレータが返ってくるが、この関数の書き方として、例えば

def pairwise(iterable):
  itnext = iter(iterable).next
  while True: # ■無限ループ?
    yield itnext(), itnext()

のように、一見無限ループに見えるような場合があったりして、直感的にわかりにくいかも。
これは、<iterator>.next が、終了条件を満たすと、例外(StopIteration)を返すように定義されているため、これによって停止するようになっている、と。

例えば、

import traceback

def pairwise(iterable):
  itnext = iter(iterable).next
  while True: # ■無限ループ?
    try:
      yield itnext(), itnext()
    except StopIteration:
      print traceback.format_exc()
      raise

for (key, val) in pairwise(['a',1,'b',2,'c',3]):
  print key, val

の結果は、

a 1
b 2
c 3
Traceback (most recent call last):
  File "<stdin>", line 5, in pairwise
StopIteration

のようになる。
これは、yield itnext(), itnext() によりリストオブジェクトの終端('c', 3)まで返された後、次の itnext がコールされたタイミングで例外が発行されていることを示す。for文はこれを捉えて終了を判断している。
試しに上記ソース中の raise をコメントアウトして例外が発行されないようにすると、無限ループに陥ってしまう。