めもちょー

メモ帳代わりに使っています。

key, valueが交互にあるリストから辞書に変換する方法

概要

key, valueが交互に現れるリスト

["key1", "value1", "key2", "value2", "key3", "value3"]

これを辞書にするアルゴリズムがエレガントだと思ったのでメモします。

{"key1": "value1", "key2": "value2", "key3": "value3"}

詳細

まず、どういうときにこのリストが現れるかを説明します。
Google スプレッドシートで1セルに改行ありのkey:valueを入れると次のようになります。

1セルに複数行入っているパターンを考える

スプレッドシートをTSVとしてダウンロードします。
ダウンロードしたTSVを端末で表示してみると、1セル内での改行はSpaceに置き換わっていることが分かります。

1セル内の改行はspaceに置き換わっていることが分かる

もともと改行であった空白と、: にある空白でsplit()すると最初に示したリストになりました。

import csv


def main():
    with open("無題のスプレッドシート - シート1 (1).tsv", "r") as f:
        reader = csv.reader(f, delimiter="\t")
        for row in reader:
            _, kvs = row
            print(kvs.replace(":", "").split(" "))


if __name__ == "__main__":
    main()


# ['key1', 'value1', 'key2', 'value2', 'kye3', 'value3']
# ['key4', 'value4', 'key5', 'value5']

次にこのリストを辞書にしてみます。
奇数はkeyに偶数はvalueにするというアルゴリズムを考えつきます。

a_list = ['key1', 'value1', 'key2', 'value2', 'kye3', 'value3']
k_list = [a for i, a in enumerate(a_list) if i % 2 == 0]
v_list = [a for i, a in enumerate(a_list) if i % 2 == 1]

# 下記2つは同じ
print({k: v for k, v in zip(k_list, v_list)})  # {'key1': 'value1', 'key2': 'value2', 'kye3': 'value3'}
print(dict(zip(k_list, v_list)))  # {'key1': 'value1', 'key2': 'value2', 'kye3': 'value3'}

しかし、これ以上にエレガントな解法を見つけたので記します。
イテレータを一つ宣言して、zipに同じイテレータを2つ渡すというやり方です。
片方はkey、片方はvalueを返すイテレータのように扱えます。

a_list = ['key1', 'value1', 'key2', 'value2', 'kye3', 'value3']
it = iter(a_list)
print(dict(zip(it, it)))  # {'key1': 'value1', 'key2': 'value2', 'kye3': 'value3'}