是否有任何简单易读的方法以功能方式解析表Python?

时间:2017-09-05 09:47:21

标签: c# python linq list-comprehension

我有以下文字:

  | 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实现更高的可读性?

1 个答案:

答案 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']}