Python-Wörterbuchverständnis

386

Ist es möglich, ein Wörterbuchverständnis in Python (für die Schlüssel) zu erstellen?

Ohne Listenverständnis können Sie Folgendes verwenden:

l = []
for n in range(1, 11):
    l.append(n)

Wir können dies auf ein Listenverständnis verkürzen : l = [n for n in range(1, 11)].

Angenommen, ich möchte die Schlüssel eines Wörterbuchs auf denselben Wert setzen. Ich kann:

d = {}
for n in range(1, 11):
     d[n] = True # same value for each

Ich habe das versucht:

d = {}
d[i for i in range(1, 11)] = True

Allerdings bekomme ich eine SyntaxErrorauf die for.

Darüber hinaus (ich brauche diesen Teil nicht, sondern frage mich nur) können Sie die Schlüssel eines Wörterbuchs auf eine Reihe verschiedener Werte festlegen, wie folgt:

d = {}
for n in range(1, 11):
    d[n] = n

Ist dies mit einem Wörterbuchverständnis möglich?

d = {}
d[i for i in range(1, 11)] = [x for x in range(1, 11)]

Dies wirft auch eine SyntaxErrorauf die for.

Rushy Panchal
quelle
3
Für zukünftige Leserinformationen: Mit NumPy-Arrays können Sie mehrere Elemente auf einen einzelnen Wert oder eine Liste von Werten festlegen, wie Sie es versuchen. Wenn Sie noch keinen Grund haben, NumPy zu verwenden, lohnt es sich wahrscheinlich nicht nur für diese Funktion.
David Z

Antworten:

520

In Python 2.7+ gibt es Wörterbuchverständnisse , die jedoch nicht so funktionieren, wie Sie es versuchen. Wie ein Listenverständnis erstellen sie ein neues Wörterbuch. Sie können sie nicht zum Hinzufügen von Schlüsseln zu einem vorhandenen Wörterbuch verwenden. Außerdem müssen Sie die Schlüssel und Werte angeben, obwohl Sie natürlich auch einen Dummy-Wert angeben können, wenn Sie möchten.

>>> d = {n: n**2 for n in range(5)}
>>> print d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Wenn Sie sie alle auf True setzen möchten:

>>> d = {n: True for n in range(5)}
>>> print d
{0: True, 1: True, 2: True, 3: True, 4: True}

Was Sie anscheinend verlangen, ist eine Möglichkeit, mehrere Schlüssel gleichzeitig in einem vorhandenen Wörterbuch festzulegen. Dafür gibt es keine direkte Abkürzung. Sie können entweder eine Schleife ausführen, wie Sie es bereits gezeigt haben, oder Sie können ein Wörterbuchverständnis verwenden, um ein neues Diktat mit den neuen Werten zu erstellen und dann oldDict.update(newDict)die neuen Werte mit dem alten Diktat zusammenzuführen.

BrenBarn
quelle
15
FWIW dict.updatekann ebenso wie der dictKonstruktor eine Iterable von Schlüssel-Wert-Paaren akzeptieren
mgilson
6
Beachten Sie, dass Sie verwenden, wenn Sie ein Wörterbuch mit allen gleichen Werten erstellen möchten dict.fromkeys(). TrueVerwenden Sie also, um alle Werte auf zu setzen dict.fromkeys(range(5), True). Beachten Sie, dass der Wert nicht kopiert wird. Sie können dies daher vermeiden, wenn Sie einen veränderlichen Wert haben. Es wird von allen Schlüsseln geteilt.
Martijn Pieters
2
Hinweis: Die Schlüssel können auch das Ergebnis einer Methode sein : { n*2 : n for n in range(3) } => {0: 0, 2: 1, 4: 2}. Beides kann im selben Ausdruck erfolgen : { n*2 : n*3 for n in range(3) } => { 0: 0, 2: 3, 4: 6 }.
Zaaier
151

Sie können die dict.fromkeysKlassenmethode verwenden ...

>>> dict.fromkeys(range(5), True)
{0: True, 1: True, 2: True, 3: True, 4: True}

Dies ist der schnellste Weg, um ein Wörterbuch zu erstellen, in dem alle Schlüssel demselben Wert zugeordnet sind.

Aber Sie nicht verwenden , diese mit veränderbaren Objekten :

d = dict.fromkeys(range(5), [])
# {0: [], 1: [], 2: [], 3: [], 4: []}
d[1].append(2)
# {0: [2], 1: [2], 2: [2], 3: [2], 4: [2]} !!!

Wenn Sie nicht wirklich brauchen , um alle Tasten zu initialisieren, eine defaultdictkönnte nützlich sein , wie auch:

from collections import defaultdict
d = defaultdict(True)

Um den zweiten Teil zu beantworten, ist ein Diktatverständnis genau das, was Sie brauchen:

{k: k for k in range(10)}

Sie sollten dies wahrscheinlich nicht tun, aber Sie können auch eine Unterklasse erstellen, dictdie wie eine funktioniert, defaultdictwenn Sie überschreiben __missing__:

>>> class KeyDict(dict):
...    def __missing__(self, key):
...       #self[key] = key  # Maybe add this also?
...       return key
... 
>>> d = KeyDict()
>>> d[1]
1
>>> d[2]
2
>>> d[3]
3
>>> print(d)
{}
mgilson
quelle
Beachten Sie, dass im Fall von d = defaultdict(lambda: True)das Lambda nicht erforderlich ist, da True veränderlich ist (oder nicht sein sollte).
Rhbvkleef
28
>>> {i:i for i in range(1, 11)}
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}
NPE
quelle
22

Ich mag den @ mgilson-Kommentar sehr, denn wenn Sie zwei Iterables haben, von denen eines den Schlüsseln und das andere den Werten entspricht, können Sie auch Folgendes tun.

keys = ['a', 'b', 'c']
values = [1, 2, 3]
d = dict(zip(keys, values))

geben

d = {'a': 1, 'b': 2, 'c': 3}

ehontz
quelle
4
Verwenden von Dict Comprehension:{i:j for i in keys for j in values}
LoMaPh
11

Verwenden Sie dict () für eine Liste von Tupeln. Mit dieser Lösung können Sie in jeder Liste beliebige Werte festlegen, sofern diese dieselbe Länge haben

i_s = range(1, 11)
x_s = range(1, 11)
# x_s = range(11, 1, -1) # Also works
d = dict([(i_s[index], x_s[index], ) for index in range(len(i_s))])
Bryan
quelle
12
Als Randnotiz ist dies das gleiche wied = dict(zip(i_s,x_s))
mgilson
10

Betrachten Sie dieses Beispiel zum Zählen des Auftretens von Wörtern in einer Liste mithilfe des Wörterbuchverständnisses

my_list = ['hello', 'hi', 'hello', 'today', 'morning', 'again', 'hello']
my_dict = {k:my_list.count(k) for k in my_list}
print(my_dict)

Und das Ergebnis ist

{'again': 1, 'hi': 1, 'hello': 3, 'today': 1, 'morning': 1}
adonese
quelle
Dies ist interessant, aber nicht das effizienteste, da Sie mehrmals Schlüssel wie "Hallo" zählen werden
FuriousGeorge
7

Der Hauptzweck eines Listenverständnisses besteht darin, eine neue Liste basierend auf einer anderen Liste zu erstellen, ohne die ursprüngliche Liste zu ändern oder zu zerstören.

Anstatt zu schreiben

    l = []
    for n in range(1, 11):
        l.append(n)

oder

    l = [n for n in range(1, 11)]

du solltest nur schreiben

    l = range(1, 11)

In den beiden oberen Codeblöcken erstellen Sie eine neue Liste, durchlaufen diese und geben nur jedes Element zurück. Es ist nur eine teure Möglichkeit, eine Listenkopie zu erstellen.

Gehen Sie folgendermaßen vor, um ein neues Wörterbuch zu erhalten, bei dem alle Schlüssel basierend auf einem anderen Diktat auf denselben Wert eingestellt sind:

    old_dict = {'a': 1, 'c': 3, 'b': 2}
    new_dict = { key:'your value here' for key in old_dict.keys()}

Sie erhalten einen SyntaxError, weil beim Schreiben

    d = {}
    d[i for i in range(1, 11)] = True

Sie sagen im Grunde: "Setzen Sie meinen Schlüssel 'i für i im Bereich (1, 11)' auf True" und "i für i im Bereich (1, 11)" ist kein gültiger Schlüssel, sondern nur ein Syntaxfehler. Wenn diktierte unterstützte Listen als Schlüssel diktieren, würden Sie so etwas tun

    d[[i for i in range(1, 11)]] = True

und nicht

    d[i for i in range(1, 11)] = True

Listen sind jedoch nicht hashbar, sodass Sie sie nicht als Diktierschlüssel verwenden können.

Bonifacio2
quelle
-3

Sie können eine solche Liste nicht hashen. Versuchen Sie dies stattdessen, es werden Tupel verwendet

d[tuple([i for i in range(1,11)])] = True
Aditya Sihag
quelle