it-swarm.com.de

So führen Sie zwei Listen in ein Wörterbuch ein, ohne verschachtelte for-Schleife zu verwenden

Ich habe zwei Listen:

a = [0, 0, 0, 1, 1, 1, 1, 1, .... 99999]
b = [24, 53, 88, 32, 45, 24, 88, 53, ...... 1]

Ich möchte diese beiden Listen in einem Wörterbuch zusammenführen: 

{
    0: [24, 53, 88], 
    1: [32, 45, 24, 88, 53], 
    ...... 
    99999: [1]
}

Eine Lösung könnte die for-Schleife sein, die nicht gut und elegant aussieht, wie zum Beispiel:

d = {}
unique_a = list(set(list_a))
for i in range(len(list_a)):
    if list_a[i] in d.keys:
        d[list_a[i]].append(list_b[i])
    else:
        d[list_a] = [list_b[i]]

Dies funktioniert zwar, ist jedoch ineffizient und würde zu lange dauern, wenn die Liste sehr groß ist. Ich möchte elegantere Möglichkeiten kennenlernen, um ein solches Wörterbuch zu erstellen. 

Danke im Voraus!

18
BigD

Sie können ein defaultdict verwenden :

from collections import defaultdict
d = defaultdict(list)
list_a = [0, 0, 0, 1, 1, 1, 1, 1, 9999]
list_b = [24, 53, 88, 32, 45, 24, 88, 53, 1]
for a, b in Zip(list_a, list_b):
   d[a].append(b)

print(dict(d))

Ausgabe:

{0: [24, 53, 88], 1: [32, 45, 24, 88, 53], 9999: [1]}
30
Ajax1234

Alternative itertools.groupby() Lösung:

import itertools

a = [0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3]
b = [24, 53, 88, 32, 45, 24, 88, 53, 11, 22, 33, 44, 55, 66, 77]

result = { k: [i[1] for i in g] 
           for k,g in itertools.groupby(sorted(Zip(a, b)), key=lambda x:x[0]) }
print(result)

Die Ausgabe:

{0: [24, 53, 88], 1: [24, 32, 45, 53, 88], 2: [11, 22, 33, 44, 55, 66], 3: [77]}
13
RomanPerekhrest

Keine ausgefallenen Strukturen, nur ein einfaches altes Wörterbuch.

d = {}
for x, y in Zip(a, b):
    d.setdefault(x, []).append(y)
5
coldspeed

Sie können dies mit einem Diktierverständnis machen:

list_a = [0, 0, 0, 1, 1, 1, 1, 1]
list_b = [24, 53, 88, 32, 45, 24, 88, 53]
my_dict = {key: [] for key in set(a)}  # my_dict = {0: [], 1: []}
for a, b in Zip(list_a, list_b):
    my_dict[a].append(b)
# {0: [24, 53, 88], 1: [32, 45, 24, 88, 53]}

Seltsamerweise können Sie diese Funktion nicht mit dict.fromkeys(set(list_a), []) ausführen, da dies den Wert aller Schlüssel gleich dem same empty-Array setzt:

my_dict = dict.fromkeys(set(list_a), [])  # my_dict = {0: [], 1: []}
my_dict[0].append(1)  # my_dict = {0: [1], 1: [1]}
4
Engineero

Eine pandas-Lösung:

Konfiguration:

import pandas as pd

a = [0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 4, 4]

b = pd.np.random.randint(0, 100, len(a)).tolist()

>>> b
Out[]: [28, 68, 71, 25, 25, 79, 30, 50, 17, 1, 35, 23, 52, 87, 21]


df = pd.DataFrame(columns=['Group', 'Value'], data=list(Zip(a, b)))  # Create a dataframe

>>> df
Out[]:
    Group  Value
0       0     28
1       0     68
2       0     71
3       1     25
4       1     25
5       1     79
6       1     30
7       1     50
8       2     17
9       2      1
10      2     35
11      3     23
12      4     52
13      4     87
14      4     21

Lösung:

>>> df.groupby('Group').Value.apply(list).to_dict()
Out[]:
{0: [28, 68, 71],
 1: [25, 25, 79, 30, 50],
 2: [17, 1, 35],
 3: [23],
 4: [52, 87, 21]}

Komplettlösung:

  1. erstellen Sie einen pd.DataFrame aus den Eingabelisten. a heißt Group und b heißt Value.
  2. df.groupby('Group') erstellt Gruppen basierend auf a
  3. .Value.apply(list) ruft die Werte für jede Gruppe ab und wandelt sie in list um.
  4. .to_dict() konvertiert die resultierende DataFrame in dict

Zeitliche Koordinierung:

So erhalten Sie eine Vorstellung von Timings für einen Testsatz von 1.000.000 Werten in 100.000 Gruppen:

a = sorted(np.random.randint(0, 100000, 1000000).tolist())
b = pd.np.random.randint(0, 100, len(a)).tolist()
df = pd.DataFrame(columns=['Group', 'Value'], data=list(Zip(a, b)))

>>> df.shape
Out[]: (1000000, 2)

%timeit df.groupby('Group').Value.apply(list).to_dict()
4.13 s ± 9.29 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Aber um ehrlich zu sein, ist es wahrscheinlich weniger effizient als itertools.groupby von @RomanPerekhrest oder defaultdict von @ Ajax1234.

3
FabienP

Vielleicht vermisse ich den Punkt, aber ich werde wenigstens versuchen zu helfen. Wenn Sie Listen erstellen müssen und diese in das Diktat aufnehmen möchten, gehen Sie wie folgt vor

a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
lists = [a, b] # or directly -> lists = [ [1, 2, 3, 4], [5, 6, 7, 8] ]
new_dict = {}
for idx, sublist in enumerate([a, b]): # or enumerate(lists)
    new_dict[idx] = sublist

ich hoffe es hilft

Oder machen Sie das Wörterbuch vorher verständlich. Da dann alle Schlüssel mit Werten für leere Listen vorhanden sind, durchlaufen Sie die Variable Zip der beiden Listen. Fügen Sie dann den Wert der zweiten Liste zum Schlüssel des ersten Namens des Wörterbuchs hinzu. oder if-Anweisungen), um zu sehen, ob der Schlüssel vorhanden ist oder nicht, weil das Wörterbuch vorher verstanden wurde:

d={k:[] for k in l}
for x,y in Zip(l,l2):
   d[x].append(y)

Jetzt:

print(d)

Ist:

{0: [24, 53, 88], 1: [32, 45, 24, 88, 53], 9999: [1]}
0
U9-Forward