2016-06-30 4 views
1

sagen, dass ich dieses verschachtelte Wörterbuch haben:Python: Wie ein verschachteltes Wörterbuch als eine komplexe Tabelle mit variablen Zeilen zu drucken?

d = {'Ben': {'wo_mana': ['Strength = 1.10', 'Speed = 1.50'], 'wi_mana': ['Int = 1.20'], 'Skill': 'true', 'Magic': 'false'}, 
    'Tom': {'wi_mana': ['Int = 1.40'], 'wo_mana': ['Agility = 1.60'], 'Skill': 'true', 'Magic': 'true'}} 

Die Schlüssel und Werte sind nicht von mir selbst definiert, sie sind tatsächlich aus einer Datei extrahiert Daten.

Die Anzahl der Werte für SkillMagic und festgelegt ist, die jedoch 1.

ist, die Anzahl der Werte für wo_mana und wi_mana ist unfixierten ab, das 1, 2, 3, 4 usw.

Im obigen Beispiel haben wo_mana 2 Werte für Ben.

Mein Ziel ist es, in einer Tabelle (mit einem Tab getrennt) zu drucken und wenn in Excel geöffnet, sieht es wie folgt aus:

Name Skill Magic wo_mana   wi_mana 
Ben true false Strength = 1.10 Int = 1.20 
       Speed = 1.50 
Tom true true Agility = 1.60 Int = 1.40 

Beachten Sie, dass die wo_mana und wi_mana Spalten für jeden Menschen, haben mehrere Zeilen.

ich das csv Modul zu verwenden haben versucht, mein Code:

import csv, itertools 

header = ['Name', 'Skill', 'Magic', 'wo_mana', 'wi_mana'] 

with open('output.csv', 'w') as f: 
    w = csv.DictWriter(f, header) 
    w.writeheader() 
    for key, val in sorted(d.items()): 
     row = {'Name': key} 
     row.update(val) 
     w.writerow(row) 

Meine Ausgabe:

Name,Skill,Magic,wo_mana,wi_mana 
Ben,true,false,"['Strength = 1.10', 'Speed = 1.50']",['Int = 1.20'] 
Tom,true,true,['Agility = 1.60'],['Int = 1.40'] 

So sieht es aus wie es nicht geeignet ist, die mehrere Zeilen Teil drucken mit csv

Also muss ich vielleicht string formatting verwenden? Kann jemand den Tisch so drucken? Jede Hilfe würde sehr geschätzt werden.

+0

In welches Format soll die Tabelle gedruckt werden, für die Spalte wo_mana und wi_mana? – wolframalpha

+0

@wolframalpha Eine Tabelle getrennt mit Tab oder Komma, einschließlich 'Name',' Skill', 'Magic' sowie' wo_mana' und 'wi_mana', sie müssen in der gleichen Tabelle –

+0

@wolframalpha Ich habe angegeben, wie ich meine möchte Tabelle sieht wie am Anfang meines Beitrags aus. –

Antwort

1

Hier können Sie (bearbeitet) gehen:

import csv, itertools 
d = {'Ben': {'wo_mana': ['Strength = 1.10'], 'wi_mana': ['Int = 1.20'], 'Skill': 'true', 'Magic': 'false'}, 
    'Tom': {'wi_mana': ['Int = 1.40'], 'wo_mana': ['Agility = 1.60'], 'Skill': 'true', 'Magic': 'true'}} 


header = ['Name', 'Skill', 'Magic', 'wo_mana', 'wi_mana'] 

with open('output.csv', 'w') as f: 
    w = csv.DictWriter(f, header) 
    w.writeheader() 
    for key, val in sorted(d.items()): 
     row = {'Name': key} 
     # print val 


     wo_mana = [item for item in val['wo_mana']] 
     wi_mana = [item for item in val['wi_mana']] 
     val['wo_mana'] = wo_mana[0] 
     val['wi_mana'] = wi_mana[0]  

     row.update(val) 
     w.writerow(row) 
     dict_list = [] 
     if len(wi_mana) > len(wo_mana): 

      for index, item in enumerate(wo_mana): 
       dict_ = {} 
       dict_['wi_mana'] = wi_mana[index] 
       dict_['wo_mana'] = wo_mana[index] 
       # print dict_ 

       dict_list.append(dict_) 
      [dict_list.append({'wi_mana': item}) for item in wi_mana[len(wo_mana):]] 
     else: 

      for index, item in enumerate(wi_mana): 
       dict_ = {} 
       dict_['wi_mana'] = wi_mana[index] 
       dict_['wo_mana'] = wo_mana[index] 
       # print dict_ 
       dict_list.append(dict_) 
      [dict_list.append({'wo_mana': item}) for item in wo_mana[len(wi_mana):]] 
     # print dict_list 
     if len(dict_list) > 1: 
      [w.writerow(dict_) for dict_ in dict_list[1:]] 

Das funktioniert! Gib mir Bescheid.

Edit: Nach der Frage:

However, the number of values for wo_mana and wi_mana is unfixed, which can be 1, 2, 3, 4 etc.

So hatte ich angenommen, gäbe es keine KeyError sein. Nach den modifizierten Aussagen in den Kommentaren hier ist die Lösung:

Es ist nicht richtig auf verschiedene Bedingungen getestet und auf das, was ich aus den Kommentaren verstanden es gut funktioniert, lassen Sie mich, wenn irgendein Problem kennen:

import csv, itertools 
d = {'Ben': {'Skill': 'true', 'Magic': 'false'}, 
    'Tom': {'wo_mana': ['Strength = 1.10'], 'wi_mana': ['Int = 1.20', 'O_o'], 'mana': ['Int = 1.20', 'dsadas', 'whatever', '-_-'], 'Skill': 'true', 'Magic': 'true'}} 


header = ['Name', 'Skill', 'Magic', 'wo_mana', 'wi_mana', 'mana'] 

with open('output.csv', 'w') as f: 
    w = csv.DictWriter(f, header) 
    w.writeheader() 
    for key, val in sorted(d.items()): 
     row = {'Name': key} 
     # print val 
     row.update(val) 
     dictionary_containing_list = {key: val[key] for key in val if type(val[key])==list} 
     if dictionary_containing_list: 
      max_length = len(max(dictionary_containing_list.iteritems(), key=lambda x: len(x[1]))[1]) 
      dict_list = [] 
      for i in range(max_length): 
       dict_ = {} 
       for key, val_list in dictionary_containing_list.iteritems(): 
        try: 
         dict_[key] = val_list[i] 
        except IndexError: 
         pass 
       dict_list.append(dict_) 
       row.update(dict_list[0]) 
      print dict_list 
     w.writerow(row) 
     if dictionary_containing_list: 
      [w.writerow(dict_) for dict_ in dict_list[1:]] 

Die Lösung ist sehr generisch und Sie können so viele Nummern von mana s/Spalten hinzufügen und es wird funktionieren. Denken Sie daran, den genauen Spaltennamen an die header Liste anzufügen!

+0

Ja, es funktioniert! Vielen Dank! Ich werde Sie wissen lassen, wenn ich auf ein Problem stoße. –

+0

Hallo, ich teste deinen Code mit meiner tatsächlichen Datei, und ich habe einen 'KeyError' während der Ausführung dieser zwei Zeile' wo_mana = [Element für Element in val ['wo_mana]] 'und' wi_mana = [Element für Element in val ['wi_mana]] ', wie wird diese Zeile nur ausgeführt, wenn' wo_mana' oder 'wi_mana' existiert? weil sie für einige "Name" nicht existieren –

+0

Okay, ich habe diese Zeilen hinzugefügt 'Wenn wo_mana/wi_mana in val.keys():' um zu überprüfen, ob die Schlüssel existieren, habe ich jetzt ein anderes Problem, welche Änderungen ich machen soll wenn ein anderer 'Schlüssel' existiert, zum Beispiel' mana', und dasselbe wie 'wo_mana' und' wi_mana', kann es mehrere Zeilen haben. –