l = ["a", "b", "c", "d", "e"]
このリストを次のような辞書に変換したい:
d = {"a": "b", "c": "d", "e": ""}
したがって、基本的には、偶数がキーになり、オッズが値になります。 if文を使用したforループなど、「非Python的な」方法でそれを実行できることは知っていますが、これを実現するには、より「Python的な」方法があるはずです。だから、私は助けに感謝します:)
通常の grouper recipe を使用すると、次のことができます。
Python 2:
d = dict(itertools.izip_longest(*[iter(l)] * 2, fillvalue=""))
Python 3:
d = dict(itertools.Zip_longest(*[iter(l)] * 2, fillvalue=""))
あなたはまだ何を考えているなら!あなたは一人ではないでしょう、実際にはそれほど複雑ではありません、説明させてください。
奇数のエントリ(1からカウント)を連続する偶数エントリにマップされるキーとして使用して、次のリストを辞書に変換します。
l = ["a", "b", "c", "d", "e"]
ディクショナリを作成するには、組み込みの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, e
とb, 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つは、奇数の長さのリストに空の値を追加することかもしれません。少し変数は退屈ではありますが、append
とif
ステートメントを使用することもできます。
>>> 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!
私は再帰に行きます:
l = ['a', 'b', 'c', 'd', 'e', ' ']
d = dict([(k, v) for k,v in Zip (l[::2], l[1::2])])
それがあなたに役立つかどうかはわかりませんが、私にはうまくいきます:
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)))