webentwicklung-frage-antwort-db.com.de

python Liste in Wörterbuch konvertieren

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

Ich möchte diese Liste in ein Wörterbuch wie das folgende konvertieren:

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

Im Grunde genommen sind die Abschlüsse also Schlüssel, während die Gewinnchancen Werte sind. Ich weiß, dass ich es auf eine "nicht-pythonische" Weise tun kann, wie zum Beispiel eine for-Schleife mit if-Anweisungen, aber ich glaube, dass es eine "pythonischere" Weise geben sollte, um dies zu erreichen. Also, ich freue mich über jede Hilfe :)

70
Shaokan

Mit dem üblichen Grouper-Rezept können Sie Folgendes tun:

Python 2:

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

Python 3:

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

Wenn Sie immer noch darüber nachdenken, was die! Du wärst nicht alleine, es ist eigentlich gar nicht so kompliziert, lass es mich erklären.

So verwandeln Sie eine Liste nur mit integrierten Funktionen in ein Wörterbuch

Wir wollen die folgende Liste in ein Wörterbuch umwandeln, indem wir die ungeraden Einträge (von 1 an gezählt) als Tasten verwenden, die ihren aufeinanderfolgenden geraden Einträgen zugeordnet sind.

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

dict ()

Um ein Wörterbuch zu erstellen, können wir die eingebaute Funktion dict für Zuordnungstypen verwenden. Gemäß Handbuch werden die folgenden Methoden unterstützt.

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

Die letzte Option schlägt vor, dass wir eine Liste von Listen mit 2 Werten oder (key, value) Tupel, also wollen wir unsere sequentielle Liste in:

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

Wir werden auch in die Funktion Zip eingeführt, eine der eingebauten Funktionen , die im Handbuch erklärt wird:

gibt eine Liste von Tupeln zurück, wobei das i-te Tupel das i-te Element aus jedem der Argumente enthält

Mit anderen Worten, wenn wir unsere Liste in zwei Listen umwandeln können, a, c, e und b, d dann Zip erledigt den Rest.

schnittnotation

Slicings , das wir zusammen mit Strings und weiter unten im Abschnitt List sehen, in dem hauptsächlich der Bereich verwendet wird oder kurze Scheibe Notation, aber das ist, was die lange Scheibe Notation sieht aus wie und was wir mit Schritt erreichen können:

>>> 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'}

Obwohl dies der einfachste Weg ist, die beteiligten Mechanismen zu verstehen, gibt es einen Nachteil, da Slices jedes Mal neue Listenobjekte sind, wie in diesem Klonbeispiel zu sehen ist:

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

>>> b is a
True

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

>>> b is a
False

Auch wenn b wie a aussieht, handelt es sich jetzt um zwei separate Objekte, weshalb wir lieber das Grouper-Rezept verwenden.

zackenbarsch Rezept

Obwohl der Grouper als Teil des itertools-Moduls erklärt wird, funktioniert er auch mit den Grundfunktionen einwandfrei.

Etwas ernstes Voodoo, oder? =) Aber eigentlich nichts anderes als ein bisschen Syntaxzucker für die Würze, das Zackenbarschrezept wird durch den folgenden Ausdruck erreicht.

*[iter(l)]*2

Was mehr oder weniger zu zwei Argumenten desselben Iterators in einer Liste führt, wenn das Sinn macht. Lassen Sie es uns aufschlüsseln, um Licht ins Dunkel zu bringen.

Zip für die kürzeste

>>> 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'}

Wie Sie sehen, bleiben die Adressen für die beiden Iteratoren gleich. Wir arbeiten also mit demselben Iterator, von dem Zip zuerst einen Schlüssel erhält und dann jedes Mal einen Wert und einen Schlüssel und einen Wert, wenn Sie denselben Iterator betätigen, um das zu erreichen, was wir getan haben mit den Scheiben viel produktiver.

Sie würden sehr viel dasselbe mit dem Folgenden erreichen, das einen kleineren Was der? Faktor vielleicht trägt.

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

Was ist mit dem leeren Schlüssel e, wenn Sie bemerkt haben, dass er in allen Beispielen fehlt, weil Zip das kürzeste der beiden Argumente auswählt, also was sollen wir tun?.

Nun, eine Lösung könnte darin bestehen, Listen mit ungerader Länge einen leeren Wert hinzuzufügen. Sie können auch append und eine if -Anweisung verwenden, die den Trick ausführen würde, wenn auch etwas langweilig, oder?

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

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

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

Nun, bevor Sie die Achseln zucken, um zu gehen, tippen Sie from itertools import izip_longest Sie werden überrascht sein, dass dies nicht erforderlich ist. Wir können das Gleiche, noch besser, meiner Meinung nach mit den eingebauten Funktionen allein erreichen.

karte für längste

Ich bevorzuge die Verwendung der map () -Funktion anstelle von izip_longest () , die nicht nur eine kürzere Syntax verwendet, sondern auch einen Import erfordert, sondern eine tatsächliche None Leerwert bei Bedarf, automatisch.

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

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

Vergleicht man die Leistung der beiden Methoden, wie von KursedMetal hervorgehoben, so ist klar, dass das itertools-Modul die Kartenfunktion bei großen Volumina bei weitem übertrifft, wie ein Benchmark gegenüber 10 Millionen Datensätzen zeigt.

$ 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

Die Kosten für den Import des Moduls gehen jedoch zu Lasten kleinerer Datensätze, bei denen die Karte viel schneller bis zu 100.000 Datensätze zurückgibt, wenn sie von Kopf zu Kopf kommen.

$ 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

Sehen Sie nichts dazu! =)

nJoy!

136
nickl-

Ich würde für Rekursionen gehen:

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

Ich bin mir nicht sicher, ob es dir helfen würde oder nicht, aber es funktioniert für mich:

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)))
2