it-swarm.com.de

Wörterbuch in Liste sortieren

Es gibt bereits viele Fragen zum Sortieren von Wörterbüchern, aber ich finde nicht die richtige Antwort auf meine Frage.

Ich habe das Wörterbuch v:

v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0}

Wir müssen das Wörterbuch v in eine sortierte Liste umwandeln.

lijst(v) = [1.0, -2.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.5]

Ich habe versucht, mit diesem Code zu arbeiten:

def lijst(x):
    return sorted(x.items(), key=lambda x: x[1])

Dies ist die Liste, die ich erhalte:

lijst(v) = [(1, -2.0), (0, 1.0), (10, 3.5), (3, 4.0)]

Weiß jemand, wie man dies in eine Liste von Werten umwandelt, die nach ihrem Schlüssel sortiert sind, wobei die fehlenden Werte mit Null aufgefüllt werden?

15
itseva

Verwenden Sie einfach itertools.chain.from_iterable , um Ihr Ergebnis (die Liste der Tupel) zu reduzieren:

>>> import itertools

>>> list(itertools.chain.from_iterable([(1, -2.0), (0, 1.0), (10, 3.5), (3, 4.0)]))
[1, -2.0, 0, 1.0, 10, 3.5, 3, 4.0]

Falls ich Ihre ursprüngliche Anfrage falsch verstanden habe und das Wörterbuch einen "spärlichen Vektor" darstellt (wobei die Schlüssel die Indizes sind), können Sie einfach eine Liste mit Nullen auffüllen:

>>> res = [0.0]*(max(v)+1)       # create a dummy list containing only zeros
>>> for idx, val in v.items():   # populate the requested indices
...     res[idx] = val 
>>> res
[1.0, -2.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.5]

Wenn Sie NumPy haben, können Sie auch die for-Schleife umgehen:

>>> import numpy as np

>>> arr = np.zeros(max(v)+1)
>>> arr[list(v.keys())] = list(v.values())
>>> arr
array([ 1. , -2. ,  0. ,  4. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  3.5])

Der letzte Ansatz beruht auf der Tatsache, dass die Reihenfolge von keys und values zwar willkürlich ist, sie sich jedoch direkt entsprechen, solange das Wörterbuch nicht geändert wird:

Schlüssel und Werte werden in einer willkürlichen Reihenfolge durchlaufen, die nicht zufällig ist, je nach Python-Implementierung unterschiedlich ist und von der Geschichte des Einfügens und Löschens des Wörterbuchs abhängt. Wenn Schlüssel-, Werte- und Elementansichten ohne zwischenzeitliche Änderungen des Wörterbuchs durchlaufen werden, entspricht die Reihenfolge der Elemente direkt.

Quelle 4.10.1. Wörterbuchansichtobjekte

11
MSeifert

Sie können dies mit chain von itertools versuchen:

from itertools import chain

v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0}

final_output = list(chain(*sorted(v.items(), key=lambda x: x[1])))

Ausgabe:

[1, -2.0, 0, 1.0, 10, 3.5, 3, 4.0]
6
Ajax1234

Eine Möglichkeit, die Paare (Schlüssel, Wert) zu verketten, ist die Verwendung von sum() mit einem Anfangswert:

>>> sum(sorted(v.items(), key=lambda x:x[1]), ())
(1, -2.0, 0, 1.0, 10, 3.5, 3, 4.0)

Dies gibt einen Tupel zurück. Übergeben Sie es an list(), wenn Sie wirklich eine Liste benötigen.

P.S. Wie von @MSeifert in den Kommentaren zutreffend hervorgehoben, hat dies fast sicher eine O (n ** 2) - Zeitkomplexität, während list(chain(...)) wahrscheinlich linear amortisiert wird.

5
NPE

Eine andere Option ist die Verwendung der yield from-Syntax eingeführt in Python 3.3 :

>>> lst = [(1, -2.0), (0, 1.0), (10, 3.5), (3, 4.0)]
>>> list([(yield from tup) for tup in lst])
[1, -2.0, 0, 1.0, 10, 3.5, 3, 4.0]
>>> 

Caveat: Beachten Sie, dass die Verwendung von yield from auf diese Weise innerhalb des Listenverständnisses nicht "offizielle Syntax" sein kann und einige (einschließlich Guido) als Fehler betrachten .

4
Christian Dean

Sie können Listenverständnis verwenden, um zu erreichen, was Sie möchten, zum Beispiel:

wenn Sie 0.0 Platzhalter für nicht verfügbare Artikel behalten möchten:

[v.get(i, 0.0) for i in range(max(v.keys())+1)]

ausgabe:

[1.0, -2.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.5]

Wenn Sie keine 0.0 Platzhalter möchten, können Sie Folgendes verwenden:

[v.get(i) for i in range(max(v.keys())+1) if v.get(i) is not None]

ausgabe:

[1.0, -2.0, 4.0, 3.5]

Erklärung:

wenn Sie range() verwenden, wird eine sortierte Liste erstellt, sodass Sie sich keine Gedanken über die Sortierung machen müssen. Dann wird versucht, Elemente aus dem Wörterbuch gemäß dieser Liste abzurufen. Wenn der Schlüssel nicht vorhanden ist, wird im ersten Beispiel ein 0.0 zurückgegeben, im zweiten Beispiel wird None zurückgegeben und aufgrund des if-statement im Ausdruck ignoriert.

BEARBEITEN:

Wie Christian erwähnt, können Sie die 2. Option für mehr Effizienz ändern:

[v[i] for i in range(max(v.keys())+1) if i in v]

Dadurch wird vermieden, dass v.get(i) zweimal aufgerufen wird.

2
Moe A

Dies ist keine strikte Beantwortung der Frage, sondern es wird versucht zu verstehen, was Sie erreichen möchten. Wenn Sie versuchen, spärliche Vektoren zu implementieren, sollten Sie, bevor Sie sich mit einer neuen Implementierung beschäftigen, nach scipy.sparse suchen.

Zum Beispiel:

from scipy.sparse import dok_matrix
v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0}
m = dok_matrix((11,1))
m.update(v)

Der Vorteil spärlicher Matrizen besteht darin, dass sie (abhängig vom Anteil der Elemente, die nicht Null sind) weniger Speicher benötigen und/oder schnellere Berechnungen zulassen.

0
Luca Citi