我有一个看起来像这样的dicts列表(可能看起来像这样,我真的不知道它们包含哪些数据):
data = [
{'k1': 'v1-a', 'k2': 'v2-a', 'k3': 'v3-a'},
{'k1': 'v1-b', 'k3': 'v3-b'},
{'k1': 'v1-c', 'k2': 'v2-c', 'k3': 'v3-c'},
{'k1': 'v1-d', 'k2': 'v2-d', 'k3': 'v3-d'}
]
目标是将其变成一个如下所示的字符串:
||k1||k2||k3||
|v1-a|v2-a|v3-a|
|v1-b||v3-b|
|v1-c|v2-c|v3-c|
|v1-d|v2-d|v3-d|
问题本身并不复杂,但我提出的解决方案是如此丑陋以至于我几乎不想使用它。
我目前得到的是:
from pandas import DataFrame
// data = ...
df = DataFrame.from_dict(data).fillna('')
body = '||{header}||\n{data}'.format(
header='||'.join(df.columns.values.tolist()),
data='\n'.join(['|{}|'.format('|'.join(i)) for i in df.values.tolist()])
)
这不仅仅是丑陋的,它取决于熊猫,这是巨大的(我不想仅仅依靠这个库)!
如果有一个很好的方法来获取标题列表和dict中的值列表列表,上面的解决方案将在没有pandas的情况下工作。但是python 2
并不保证字典顺序,所以我不能指望.values()
给我正确的信息。
我错过了itertools
或collections
中的任何内容吗?
答案 0 :(得分:1)
这适用于Python 3和2.7。试一试:https://repl.it/repls/VividMediumturquoiseAlbino
all_keys = sorted({key for dic in data for key in dic.keys()})
header = "||" + "||".join(all_keys) + "||"
lines = [header]
for row in data:
elems_on_row = [row.get(key, "") for key in all_keys]
current_row = "|" + "|".join(elems_on_row) + "|"
lines.append(current_row)
wikistr = "\n".join(lines)
print(wikistr)
答案 1 :(得分:0)
纯Python中的答案是遍历列表,因此每个字典两次。 在第一次运行中,您可以收集所有不同的键,在第二次运行中,您可以构建您的wiki格式化字符串输出。
我们首先收集可以将集合用作存储的密钥:
keys = set()
for dict_ in data:
keys.update(set(dict_.keys())
keys = sorted(keys)
现在我们有了一组唯一键,我们可以再次浏览列表输出:
wiki_output = ''
wiki_output = '||' + '||'.join(keys) + '||'
for dict_ in data:
for key in keys:
wiki_output += '|' + dict_.get(key, '')
wiki_output += '|\n'
我们去......
答案 2 :(得分:0)
一种方法是使用csv.DictWriter
来处理格式,StringIO
收集输入,defaultdict
进行一些创意作弊。这是否更漂亮是有争议的。
from StringIO import StringIO
from collections import defaultdict
from csv import DictWriter
output = StringIO()
keys = list(set(key for datum in data for key in datum.keys()))
header = '|'.join('|{}|'.format(key) for key in keys)
output.write(header + '\n')
fields = [''] + keys + [''] # provides empty fields for starting and ending |
writer = DictWriter(output, fields, delimiter = '|')
for row in data:
writer.writerow(defaultdict(str, **row)) # fills in the empty fields
output.seek(0)
result = output.read()