Ich versuche, die binären Zeichenfolgen bestimmter Zahlen basierend auf der Anzahl der Einsen in der Zeichenfolge zu gruppieren.
Das funktioniert nicht:
s = "0 1 3 7 8 9 11 15"
numbers = map(int, s.split())
binaries = [bin(x)[2:].rjust(4, '0') for x in numbers]
one_groups = dict.fromkeys(range(5), [])
for x in binaries:
one_groups[x.count('1')] += [x]
Das erwartete Wörterbuch one_groups
muss sein
{0: ['0000'],
1: ['0001', '1000'],
2: ['0011', '1001'],
3: ['0111', '1011'],
4: ['1111']}
Aber ich verstehe
{0: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'],
1: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'],
2: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'],
3: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'],
4: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111']}
Bisher ist die einzige Sache , die funktioniert hat, wenn ich one_groups[x.count('1')] = one_groups.get(x.count('1')) + [x]
stattone_groups[x.count('1')] += [x]
Aber warum ist das so? Wenn ich mich richtig erinnere, dict[key]
soll der Wert dieses Wörterbuchs nicht zurückgegeben werden, ähnlich wie es dict.get(key)
funktioniert? Ich habe diesen Thread gesehen. Warum dict.get (Schlüssel) anstelle von dict [Schlüssel]? aber es hat meine Frage für diesen speziellen Fall nicht beantwortet, da ich sicher weiß, dass das Programm nicht dazu gedacht ist, das zu bekommenKeyError
Ich habe es auch versucht, one_groups[x.count('1')].append(x)
aber das funktioniert auch nicht.
quelle
get
Rückgabe,None
wenn der Schlüssel nicht vorhanden ist oder ein angegebener Standardwert, während der[]
Indexoperator einen Fehler auslöst, wenn der Schlüssel nicht vorhanden ist.bin(x)[2:].rjust(4, '0')
kann vereinfacht werden'{:0>4b}'.format(x)
.binaries
ist Ihre Vorgehensweise für die Frage nicht relevant, sodass Sie nur ihren Wert angeben können.Antworten:
Das Problem ist die Veränderlichkeit:
one_groups = dict.fromkeys(range(5), [])
- Dadurch wird allen Schlüsseln dieselbe Liste als Wert übergeben . Wenn Sie also einen Wert ändern, ändern Sie alle.Es ist im Grunde das gleiche wie zu sagen:
Wenn Sie eine neue Liste verwenden möchten, müssen Sie dies in einer Schleife tun - entweder in einer expliziten
for
Schleife oder in einem Diktatverständnis:Dieses Ding wird für jeden Schlüssel "ausgeführt"
[]
(was gleich istlist()
), wodurch die Werte mit unterschiedlichen Listen erstellt werden.Warum
get
arbeitet? Weil Sie explizit die aktuelle Liste nehmen, aber+
eine neue Ergebnisliste erstellen. Und es spielt keine Rolle, ob es istone_groups[x.count('1')] = one_groups.get(x.count('1')) + [x]
oderone_groups[x.count('1')] = one_groups[x.count('1')] + [x]
- was zählt, ist, dass es gibt+
.Ich weiß, wie jeder sagt, dass
a+=b
es gerecht ista=a+b
, aber die Implementierung kann für die Optimierung unterschiedlich sein - im Fall von Listen+=
nur,.extend
weil wir wissen, dass wir unser Ergebnis in der aktuellen Variablen haben wollen, so dass das Erstellen einer neuen Liste Speicherverschwendung wäre.quelle
mylist = [[] * 5] * 5
und wiemylist = [[] for x in range(5)] * 5
ich es behoben hätte. Nur zur schnellen Verdeutlichung geschieht dies, wie ich verstanden habe, aufgrund der Variablen, die auf die Speicheradresse dieser leeren Liste verweisen. Bedeutet dies auch, dass das Problem nicht auftreten würde, wenn ich stattdessen Grundelemente verwenden würde?one_groups[x.count('1')] += [x]
da Sie einem Grundelementtyp keine Liste hinzufügen können. Eine bessere Lösung ist die Verwendung von defaultdict.+
Anrufe__add__
und gibt ein neues Objekt, während+=
Anrufe__iadd__
, und ist nicht erforderlich , um ein neues Objekt zurückDas Problem ist mit
one_groups = dict.fromkeys(range(5), [])
(Dadurch wird allen Schlüsseln dieselbe Liste als Wert übergeben. Wenn Sie also einen Wert ändern, ändern Sie alle.)
Sie können dies stattdessen verwenden:
one_groups = {i:[] for i in range(5)}
(Dieses Ding "führt" [] aus (was list () entspricht) für jeden Schlüssel, wodurch die Werte mit unterschiedlichen Listen erstellt werden.)
quelle
Dies ist die Hilfe zur
fromkeys
Methode von dict .Das heißt, fromkeys akzeptiert einen Wert, und selbst wenn er aufrufbar ist, wertet er ihn zuerst aus und weist diesen Wert dann allen diktierten Schlüsseln zu.
Listen sind in Python veränderbar, sodass dieselbe leere Listenreferenz zugewiesen wird und eine Änderung sie alle betrifft.
Verwenden Sie stattdessen defaultdict wie folgt:
Dies akzeptiert Zuweisungen zu nicht vorhandenen Schlüsseln und Werte werden standardmäßig zu leeren Listen (in diesem Fall).
quelle