web-dev-qa-db-ja.com

pythonリストを辞書に変換

l = ["a", "b", "c", "d", "e"]

このリストを次のような辞書に変換したい:

d = {"a": "b", "c": "d", "e": ""}

したがって、基本的には、偶数がキーになり、オッズが値になります。 if文を使用したforループなど、「非Python的な」方法でそれを実行できることは知っていますが、これを実現するには、より「Python的な」方法があるはずです。だから、私は助けに感謝します:)

70
Shaokan

通常の grouper recipe を使用すると、次のことができます。

Python 2:

d = dict(itertools.izip_longest(*[iter(l)] * 2, fillvalue=""))

Python 3:

d = dict(itertools.Zip_longest(*[iter(l)] * 2, fillvalue=""))
44
Sven Marnach

あなたはまだ何を考えているなら!あなたは一人ではないでしょう、実際にはそれほど複雑ではありません、説明させてください。

組み込み関数のみを使用してリストを辞書に変換する方法

奇数のエントリ(1からカウント)を連続する偶数エントリにマップされるキーとして使用して、次のリストを辞書に変換します。

l = ["a", "b", "c", "d", "e"]

dict()

ディクショナリを作成するには、組み込みのdict関数を使用して、 マッピングタイプ のマニュアルに従って、次のメソッドをサポートします。

dict(one=1, two=2)
dict({'one': 1, 'two': 2})
dict(Zip(('one', 'two'), (1, 2)))
dict([['two', 2], ['one', 1]])

最後のオプションは、2つの値または(key, value)タプルを含むリストのリストを提供することを示唆しているので、シーケンシャルリストを次のようにしたいです。

l = [["a", "b"], ["c", "d"], ["e",]]

Zip関数、 組み込み関数の1つ についても説明します。

タプルのリストを返します。i番目のタプルには、各引数のi番目の要素が含まれます

言い換えると、リストをa, c, eb, dの2つのリストに変換できる場合、Zipが残りを行います。

スライス表記

スライシング これは Strings とともに使用され、さらに Listセクション で使用され、主に範囲を使用しますまたはshort slice表記ですが、これはlong slice表記は次のようになり、stepで達成できること:

>>> l[::2]
['a', 'c', 'e']

>>> l[1::2]
['b', 'd']

>>> Zip(['a', 'c', 'e'], ['b', 'd'])
[('a', 'b'), ('c', 'd')]

>>> dict(Zip(l[::2], l[1::2]))
{'a': 'b', 'c': 'd'}

これは関連するメカニズムを理解する最も簡単な方法ですが、スライスは毎回新しいリストオブジェクトであるため、このクローンの例からわかるように、欠点があります。

>>> a = [1, 2, 3]
>>> b = a
>>> b
[1, 2, 3]

>>> b is a
True

>>> b = a[:]
>>> b
[1, 2, 3]

>>> b is a
False

Bはaのように見えますが、現在は2つの別個のオブジェクトであるため、代わりに grouper recipe を使用することを好みます。

ハタのレシピ

Grouperはitertoolsモジュールの一部として説明されていますが、基本機能でも完全に機能します。

真面目なブードゥー教の人ですか? =)しかし、実際にはスパイスのほんの少しの構文砂糖に過ぎず、ハタのレシピは次の式によって達成されます。

*[iter(l)]*2

リストにラップされた同じイテレータの2つの引数に変換されるのは、意味がある場合です。それを分解して光を当てましょう。

最短のジップ

>>> l*2
['a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e']

>>> [l]*2
[['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']]

>>> [iter(l)]*2
[<listiterator object at 0x100486450>, <listiterator object at 0x100486450>]

>>> Zip([iter(l)]*2)
[(<listiterator object at 0x1004865d0>,),(<listiterator object at 0x1004865d0>,)]

>>> Zip(*[iter(l)]*2)
[('a', 'b'), ('c', 'd')]

>>> dict(Zip(*[iter(l)]*2))
{'a': 'b', 'c': 'd'}

ご覧のとおり、2つのイテレータのアドレスは同じであるため、同じイテレータを使用して、Zipが最初にキーを取得し、次に同じイテレータをステップ実行するたびに値とキーと値を取得しますスライスをより生産的に。

おそらくより小さいWhat ??ファクターを伴う以下のものでも、ほぼ同じことを達成できます。

>>> it = iter(l)     
>>> dict(Zip(it, it))
{'a': 'b', 'c': 'd'}

空のキーeについては、Zipが2つの引数のうち最も短いものを選択するため、すべての例から欠落していることに気付いた場合はどうすればよいでしょうか。

解決策の1つは、奇数の長さのリストに空の値を追加することかもしれません。少し変数は退屈ではありますが、appendifステートメントを使用することもできます。

>>> if len(l) % 2:
...     l.append("")

>>> l
['a', 'b', 'c', 'd', 'e', '']

>>> dict(Zip(*[iter(l)]*2))
{'a': 'b', 'c': 'd', 'e': ''}

ここでfrom itertools import izip_longestと入力する前に肩をすくめる前に、それが不要であることを知って驚くかもしれませんが、組み込み関数だけで同じ、より良いIMHOを達成できます。

最長の地図

izip_longest() の代わりに map()関数 を使用することを好みます。これは、短い構文を使用するだけでなく、インポートを必要とせず、実際のNone空の値を割り当てることができます自動的に必要です。

>>> l = ["a", "b", "c", "d", "e"]
>>> l
['a', 'b', 'c', 'd', 'e']

>>> dict(map(None, *[iter(l)]*2))
{'a': 'b', 'c': 'd', 'e': None} 

KursedMetalが指摘したように、2つのメソッドのパフォーマンスを比較すると、1000万件のレコードに対するベンチマークが示すように、itertoolsモジュールが大容量のマップ機能よりもはるかに優れていることが明らかです。

$ time python -c 'dict(map(None, *[iter(range(10000000))]*2))'
real    0m3.755s
user    0m2.815s
sys     0m0.869s
$ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(10000000))]*2, fillvalue=None))'
real    0m2.102s
user    0m1.451s
sys     0m0.539s

ただし、モジュールのインポートにかかるコストは、小さなデータセットに大きな負荷がかかり、マップが直接到着すると最大で約10万件のレコードがより速く返されます。

$ time python -c 'dict(map(None, *[iter(range(100))]*2))'
real    0m0.046s
user    0m0.029s
sys     0m0.015s
$ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(100))]*2, fillvalue=None))'
real    0m0.067s
user    0m0.042s
sys     0m0.021s

$ time python -c 'dict(map(None, *[iter(range(100000))]*2))'
real    0m0.074s
user    0m0.050s
sys     0m0.022s
$ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(100000))]*2, fillvalue=None))'
real    0m0.075s
user    0m0.047s
sys     0m0.024s

何も見えません! =)

nJoy!

133
nickl-

私は再帰に行きます:

l = ['a', 'b', 'c', 'd', 'e', ' ']
d = dict([(k, v) for k,v in Zip (l[::2], l[1::2])])
17

それがあなたに役立つかどうかはわかりませんが、私にはうまくいきます:

l = ["a", "b", "c", "d", "e"]
outRes = dict((l[i], l[i+1]) if i+1 < len(l) else (l[i], '') for i in xrange(len(l)))
1