Python:如何将嵌套字典打印为具有可变行的复杂 table?
Python: How to print a nested dictionary as a complex table with variable rows?
假设我有这个嵌套字典:
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'}}
key和value不是我自己定义的,其实是从一个文件中提取出来的数据
Skill
和Magic
的取值个数是固定的,即1。
但是wo_mana
和wi_mana
的取值个数是不固定的,可以是1、2、3、4等
在上面的示例中,wo_mana
有 2 个值 Ben
。
我的目标是将其打印在 table 中(用制表符分隔),当在 Excel 中打开时,它看起来像这样:
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
请注意,对于每个人,wo_mana
和 wi_mana
列可以有多行。
我试过使用csv
模块,我的代码:
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)
我的输出:
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']
所以使用csv
打印多行部分看起来不是suitable
所以也许我必须使用 string formatting
?有谁知道如何打印 table 这样的?任何帮助将不胜感激。
给你(已编辑):
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:]]
这行得通!让我知道。
编辑:
根据问题:
However, the number of values for wo_mana and wi_mana is unfixed, which can be 1, 2, 3, 4 etc.
所以我假设不会有 KeyError。
根据评论中的修改语句这里是解决方案:
它没有针对各种条件进行适当的测试,根据我从评论中了解到它工作正常,如果有任何问题请告诉我:
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:]]
该解决方案非常通用,您可以添加任意数量的 mana
s/ 列,它会起作用。请记住将准确的列名附加到 header
列表中!
假设我有这个嵌套字典:
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'}}
key和value不是我自己定义的,其实是从一个文件中提取出来的数据
Skill
和Magic
的取值个数是固定的,即1。
但是wo_mana
和wi_mana
的取值个数是不固定的,可以是1、2、3、4等
在上面的示例中,wo_mana
有 2 个值 Ben
。
我的目标是将其打印在 table 中(用制表符分隔),当在 Excel 中打开时,它看起来像这样:
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
请注意,对于每个人,wo_mana
和 wi_mana
列可以有多行。
我试过使用csv
模块,我的代码:
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)
我的输出:
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']
所以使用csv
所以也许我必须使用 string formatting
?有谁知道如何打印 table 这样的?任何帮助将不胜感激。
给你(已编辑):
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:]]
这行得通!让我知道。
编辑: 根据问题:
However, the number of values for wo_mana and wi_mana is unfixed, which can be 1, 2, 3, 4 etc.
所以我假设不会有 KeyError。 根据评论中的修改语句这里是解决方案:
它没有针对各种条件进行适当的测试,根据我从评论中了解到它工作正常,如果有任何问题请告诉我:
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:]]
该解决方案非常通用,您可以添加任意数量的 mana
s/ 列,它会起作用。请记住将准确的列名附加到 header
列表中!