2015-04-01 12 views
5

Ich versuche, ein verschachteltes Wörterbuch in eine .csv-Datei zu schreiben. Hier ist ein einfaches Beispiel:Python: Verschachtelte Wörterbuch in CSV schreiben

import csv 
import itertools 

fields = [ 'org', '2015', '2014', '2013' ] 
dw  = { 'orgname1': { '2015' : 2, '2014' : 1, '2013' : 1 }, 
      'orgname2': { '2015' : 1, '2014' : 2, '2013' : 3 }, 
      'orgname3': { '2015' : 1, '2014' : 3, '2013' : 1 } 
     } 

with open("test_output.csv", "wb") as f: 
    w = csv.writer(f) 
    years = dw.values()[0].keys() 
    for key in dw.keys(): 
     w.writerow([key, [dw[key][year] for year in years]]) 

Das wird mir eine Tabelle mit zwei Spalten: Die erste enthält orgname; die zweite enthält [2, 1, 1] (oder die entsprechenden Werte aus dem Unterwörterbuch). Ich möchte eine Tabelle mit vier Spalten: eine für orgname und dann drei für die entsprechenden Listenelemente.

+0

dicts haben keine Bestellung, so dass Sie sofort in Schwierigkeiten sind –

+0

@PadraicCunningham zugestimmt. Seine Schlüssel scheinen jedoch einer lexographischen Reihenfolge zu folgen. Also, er könnte es immer noch schaffen, indem er dw.keys() sortiert und dann darüber iteriert. –

Antwort

3

Wechsel:

w.writerow([key, [dw[key][year] for year in years]]) 

An:

w.writerow([key] + [dw[key][year] for year in years]) 

Ansonsten versuchen Sie so etwas wie [orgname1, [2, 1, 1]] zum csv zu schreiben, während Sie [orgname1, 2, 1, 1] bedeuten.

Wie Padraic erwähnt, möchten Sie möglicherweise years = dw.values()[0].keys() zu years = sorted(dw.values()[0].keys()) oder years = fields[1:] ändern, um zufälliges Verhalten zu vermeiden.

+0

es ist nicht notwendig, Jahre zu sortieren, wenn Sie DictWriter verwenden würden, wie in anderen Antworten vorgeschlagen –

+0

@hexereisoftware Yeah, aber das würde nur jetzt kopieren. – matsjoyce

8

Das sieht wie ein Job für DictWriter:

import csv 
import itertools 
import sys 

fields = [ 'org', '2015', '2014', '2013' ] 
dw  = { 'orgname1': { '2015' : 2, '2014' : 1, '2013' : 1 }, 
      'orgname2': { '2015' : 1, '2014' : 2, '2013' : 3 }, 
      'orgname3': { '2015' : 1, '2014' : 3, '2013' : 1 } 
     } 

w = csv.DictWriter(sys.stdout, fields) 
for key,val in sorted(dw.items()): 
    row = {'org': key} 
    row.update(val) 
    w.writerow(row) 
+0

verdienen Sie den besten Kommentar tatsächlich, weil Sie die erste vollständige Lösung und ich mag die Art, wie Sie die dicts Update-Funktion verwendet. Ich habe das in meiner Antwort in einer separaten Funktion angepasst, um es danach noch einen Liner zu behalten. meine antwort ist also ziemlich deins, geändert in dateiausgabe und hinzugefügt header :) –

5

Alternative Implementierung mit DictWriter und mit Header

import csv 
import itertools 

fields = [ 'org', '2015', '2014', '2013' ] 
dw  = { 'orgname1': { '2015' : 2, '2014' : 1, '2013' : 1 }, 
      'orgname2': { '2015' : 1, '2014' : 2, '2013' : 3 }, 
      'orgname3': { '2015' : 1, '2014' : 3, '2013' : 1 } 
     } 

with open("test_output.csv", "wb") as f: 
    w = csv.DictWriter(f, fields) 
    w.writeheader() 
    for k in dw: 
     w.writerow({field: dw[k].get(field) or k for field in fields}) 

Ausgang:

org,2015,2014,2013 
orgname1,2,1,1 
orgname3,1,3,1 
orgname2,1,2,3 
+0

ich mag deine antwort am besten, direkt :) du könntest 'dw' mit seinen tasten sortieren, da in deiner ausgabe die orgnamen-Reihenfolge geändert wurde Eingang. mit 'sorted (dw.items())' behebt das –

+0

Liebe Python 3 Benutzer, die sich nicht blamieren wollen, verbringen Stunden damit, wie ich es gerade getan habe, wenn man nur 'open (" test_output.csv "," wb ")' für 'open (" test_output.csv "," w ", newline = '')' und die obige Lösung wird einwandfrei funktionieren. Sie erhalten ein 'ein Byte-ähnliches Objekt ist erforderlich, nicht 'str' beim Schreiben in eine Datei '' andernfalls. Sei kein Nana und versuche dein ganzes Wörterbuch in Ascii wie mich zu kodieren. – Frikster

1

Mit DictWriter gibt es keine Notwendigkeit in Sortieranlagen die Felder im voraus, seit w.writerow() wird die richtige Reihenfolge sicherstellen. Aber es macht Sinn, die Artikel selbst zu sortieren.

Also alle Zusammenstellung der oben genannten Vorschläge und das Beste aus jeder Kommissionierung, würde ich mit folgendem Code kommen:

import csv 
import itertools 

def mergedict(a,b): 
    a.update(b) 
    return a 

fields = [ 'org', '2015', '2014', '2013' ] 
dw  = { 'orgname1': { '2015' : 2, '2014' : 1, '2013' : 1 }, 
      'orgname2': { '2015' : 1, '2014' : 2, '2013' : 3 }, 
      'orgname3': { '2015' : 1, '2014' : 3, '2013' : 1 } 
     } 

with open("test_output.csv", "wb") as f: 
    w = csv.DictWriter(f, fields) 
    w.writeheader() 
    for k,d in sorted(dw.items()): 
     w.writerow(mergedict({'org': k},d)) 

Ich habe eine winzige mergedict() Funktion, die es einen Einzeiler weiter nach unten macht.

Verwandte Themen