2015-04-01 20 views
5

Bir .csv dosyasına iç içe bir sözlük yazmayı deniyorum. İşte basit bir örnek olduğu:Python: İç içe Sözlükü CSV'ye Yazma

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]]) 

Bu iki sütun ile bana bir tablo alır: İlk orgname içerir; ikincisi [2, 1, 1] (veya alt sözlükten karşılık gelen değerler) içerir. Dört sütun içeren bir tablo istiyorum: biri orgname için ve sonra karşılık gelen liste elemanları için üç.

+0

Dicts'ın siparişi yok, bu yüzden hemen dertte derttesiniz –

+0

@PadraicCunningham kabul etti. Ancak, onun anahtarları bir sözlüksel düzeni takip ediyor gibi görünüyor. Yani, o hala dw.keys() sıralama ve daha sonra üzerinde yineleme yaparak işe yarayabilir. –

cevap

3

Değişimi:

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

için:

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

Aksi takdirde, [orgname1, 2, 1, 1] demek iken, csv [orgname1, [2, 1, 1]] gibi bir şey yazmaya çalışıyorum.

Padraic'in belirttiği gibi, rasgele davranışlardan kaçınmak için years = dw.values()[0].keys() değerini years = sorted(dw.values()[0].keys()) veya years = fields[1:] olarak değiştirmek isteyebilirsiniz.

+0

yıl sıralamak gerekli değildir, ama bu sadece şimdi kopyalama olurdu. –

+0

@hexereisoftware içinde önerilen şekilde DictWriter kullanıyor olsaydınız, – matsjoyce

8

Bu DictWriter için işe benziyor: DictWriter kullanarak

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

aslında en iyi yorumu hak ediyorsun, çünkü ilk tam çözümün nerede ve ben dicts güncelleme fonksiyonunu kullanma şeklini beğeniyorum. Cevabımda, daha sonra tek bir astarı korumak için ayrı bir fonksiyona uyarladım. Bu yüzden benim cevabım çok fazla senin, dosya çıktısı değişti ve üstbilgi ekledi :) –

5

Alternatif uygulama ve başlıklarıyla

ile
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}) 

Çıktı: DictWriter kullanma

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

Ben senin cevabını en iyi, düz ileriye doğru :) sen kendi aralarında 'dw' seçerek düşünebilirsiniz. giriş. 'sort (dw.items())' kullanarak düzeltme bu –

+0

düzeltir Sevgili Python 3 kullanıcıları, kendileri yapmak zorunda olduğunuzda sadece saat açık harcamayı istemediğim gibi utandırmak istemiyorum. "," wb ")' açık ("test_output.csv", "w", newline = '') 've yukarıdaki çözüm sorunsuz çalışacaktır. Aksi halde bir dosyaya yazarken 'str' değil, bir bayt benzeri nesne gerekir. Bir nana olmayın ve tüm sözlüğünüzü benim gibi ascii'ye kodlamaya çalışın. – Frikster

1

sıralamaya gerek yoktur alanları şimdiden,'den beri 10 doğru siparişi sağlayacaktır. Ama öğeleri kendileri sıralamak mantıklı.

Yani hep birlikte yukarıdaki önerileri koyarak ve her biri en iyi toplama i aşağıdaki kodla kadar gelirdi:

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)) 

ben bir tek astar daha aşağı kılan küçük mergedict() fonksiyonu eklendi.