Die Daten sehen folgendermaßen aus:

id,outer,inner1,inner2,inner3
123,"Smith,John",a,b,c
123,"Smith,John",d,e,f
123,"Smith,John",g,h,i
456,"Williams,Tim",xx,yy,zz
456,"Williams,Tim",vv,ww,uu
456,"Miller,Ray",rrr,sss,ttt
456,"Miller,Ray",qqq,www,ppp

Ich möchte das resultierende Wörterbuch sein

{'123': {'Smith,John': 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'},
 '456': {'Williams,Tim': 'xx', 'yy', 'zz', 'vv', 'ww', 'zz'},
        {'Miller,Ray': 'rrr', 'sss', 'ttt', 'qqq', 'www', 'ppp'}}

Ich habe versucht, die akzeptierte Antwort von Python beim Erstellen eines verschachtelten Wörterbuchs aus einer CSV-Datei , aber diese Methode überschreibt das Wörterbuch in jeder Zeile, sodass nur die letzte Zeile jeder ID im Wörterbuch landet.

2
public_displYname 6 Aug. 2015 im 00:47

3 Antworten

Beste Antwort

A collection.defaultdict unter Verwendung des ersten Elements aus jeder Zeile als äußere Diktatschlüssel, dann die zweite für innere Diktatschlüssel verwenden und den Rest der Werte aus der Zeile als Wert für den inneren Diktatschlüssel zu einer Liste hinzufügen:

import csv
from collections import defaultdict
with open("in.txt" ) as f:
    next(f) # skip header
    d = defaultdict(lambda: defaultdict(list))
    r = csv.reader(f)
    for row in r:
        d[row[0]][row[1]].extend(row[2:])

from pprint import pprint as pp

pp(dict(d))

Ausgabe:

{'123': {'Smith,John': ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']},
 '456': {'Miller,Ray': ['rrr', 'sss', 'ttt', 'qqq', 'www', 'ppp'],
         'Williams,Tim': ['xx', 'yy', 'zz', 'vv', 'ww', 'uu']}}

Da Sie python3 verwenden, können wir die Schleife mit * entpacken, um den Code ein bisschen schöner zu machen:

with open("in.txt") as f:
    next(f)  # skip header
    d = defaultdict(lambda: defaultdict(list))
    r = csv.reader(f)
    for k1, k2, *vals in r:
        d[k1][k2].extend(vals))
1
Padraic Cunningham 5 Aug. 2015 im 22:05

dict.setdefault ist eine gute Möglichkeit, Datenstrukturen abzurufen und nach Bedarf zu erstellen.

import csv
import pprint

data = '''123,"Smith,John",a,b,c
123,"Smith,John",d,e,f
123,"Smith,John",g,h,i
456,"Williams,Tim",xx,yy,zz
456,"Williams,Tim",vv,ww,uu
456,"Miller,Ray",rrr,sss,ttt
456,"Miller,Ray",qqq,www,ppp
'''
data = data.splitlines()
data = csv.reader(data)

result = {}
for datum in data:
    outer = result.setdefault(datum[0], {})
    inner = outer.setdefault(datum[1], [])
    inner.extend(datum[2:])

pprint.pprint(result)
0
Robᵩ 5 Aug. 2015 im 21:56

Ja, denn in diesem Beispiel wird in dieser Zeile jedes Mal die UID angegeben:

new_data_dict[row["UID"]] = item

Stattdessen können Sie setdefault verwenden, um den Eintrag in eine Liste als Standard festzulegen und anzuhängen:

new_data_dict.setdefault(row["UID"], []).append(item)
0
R Samuel Klatchko 5 Aug. 2015 im 21:55