我有以下文字:
| job_id | brand | start_date |
| 1 | zara | now |
| 2 | zara | now |
| 3 | zara | 2017-1-1 |
| 4 | zara | 2017-1-2 |
我需要将这个表解析为一个字典数组,每个字典都是一个由标题索引的行。像这样:
[{'job_id':'1', 'brand': 'zara', 'start_date':'now'},
{'job_id':'2', 'brand': 'zara', 'start_date':'now'}...]
我非常喜欢函数式编程和不可变性,所以我尝试在python中执行以下代码:
def remove_empty_entries(data):
return [d for d in data if d]
rows = table.split('\n')
headers = remove_empty_entries([ row.strip() for row in rows[0].split('|') ])
datarow = [remove_empty_entries(map(lambda x: x.strip(), row.split('|')))
for row in rows[1:]]
result = [ dict(zip(headers, row)) for row in datarow ]
这段代码让我觉得与C#和LINQ相比,python处理,过滤和转换列表或其他数据结构过于复杂。与流畅的API(如LINQ)相比,我发现列表的复杂性更难以阅读。我会做这样的事情:
// This will give me the lines already trimmed of any extra space
lines = table.split('\n')
.Select(line => line.split('|').Select(value => value.Trim()).Where(value => !value.IsNullOrEmpty())).ToList()
header = lines[0]
rowdata = lines.Skip(1).ToList()
rowdata.Select(row => header.Zip(row).ToDictionary(x => x.Item1))
我刚刚在没有测试的情况下开发了这个,所以我不确定这个代码是否编译,但我希望我能说清楚。我可以在lambdas中做一些提取方法来提高可读性。
在保持函数式编程的同时,有没有办法在这个特定的操作中用Python实现更高的可读性?
答案 0 :(得分:1)
是的,你做的太多了。我只是坚持列表推导:
rows = [[col.strip() for col in row.split('|')] for row in table.splitlines()]
headers = [col for col in rows[0] if col]
result = [dict(zip(headers, (c for c in row if c))) for row in rows[1:]]
演示:
>>> rows = [[col.strip() for col in row.split('|')] for row in table.splitlines()]
>>> headers = [col for col in rows[0] if col]
>>> result = [dict(zip(headers, (c for c in row if c))) for row in rows[1:]]
>>> from pprint import pprint
>>> pprint(result)
[{'brand': 'zara', 'job_id': '1', 'start_date': 'now'},
{'brand': 'zara', 'job_id': '2', 'start_date': 'now'},
{'brand': 'zara', 'job_id': '3', 'start_date': '2017-1-1'},
{'brand': 'zara', 'job_id': '4', 'start_date': '2017-1-2'}]
对于更通用的方法,您可以使用asciitable
package:
>>> import asciitable
>>> asciitable.read(table, Reader=asciitable.FixedWidth, numpy=False, exclude_names=[''])
{'job_id': [1, 2, 3, 4], 'brand': ['zara', 'zara', 'zara', 'zara'], 'start_date': ['now', 'now', '2017-1-1', '2017-1-2']}
>>> pprint(_)
{'brand': ['zara', 'zara', 'zara', 'zara'],
'job_id': [1, 2, 3, 4],
'start_date': ['now', 'now', '2017-1-1', '2017-1-2']}