我有一个奇怪的数据结构,该结构是我无法控制的外部服务返回给我的。
该数据本质上是一个字典列表,但在陌生的路上斩:它是返回字典的列表,其中每个字典有一个单一的关键。从该列表中获取多个元素将产生字典中的所有键。
在代码中:
[ {'id': 1}, {'a': a}, {'b': b}, {'c': c},
{'id': 2}, {'a': a}, {'b': b}, {'c': c},
{'id': 3}, {'a': a}, {'b': b}, {'c': c},
...
]
我要重建的每本字典都以id
字典开头。找到id
密钥后,我需要从列表中获取所有值,直到找到另一个id
。
我当前的解决方案是:
def split_groups(data, key='id'):
groups = []
for e in data:
if key in e: # begin new group
groups.append(list())
groups[-1].append(e)
return groups
可以,但是很丑。我知道itertools.groupby
:但是,我真的不明白如何使用它。
这行的结果是:
[(k, list(g)) for k, g in groupby(data, lambda d: d.get('id') is not None)]
是:
[(True, [{'id': 1}]),
(False, [{'a': 1}, {'b': 2}, {'c': 3}]),
(True, [{'id': 2}]),
(False, [{'a': 1}, {'b': 2}, {'c': 3}]),
(True, [{'id': 3}]),
(False, [{'a': 1}, {'b': 2}, {'c': 3}])]
如您所见,该id
词典与以下值以不同的组结尾。
我究竟做错了什么?
在Sumukh Barve回答之后,我想groupby并不是我工作的正确工具。我当前的代码将用于生产;只是为了好玩,我这样重写它:
def split_groups(data, key='id'):
if not data:
return []
predicate = lambda d: key not in d
head, tail = data[0], data[1:]
group = [[head] + list(takewhile(predicate, tail))]
rest = list(dropwhile(predicate, tail))
group.extend(split_groups(rest, key))
return group
这是一种效率低下,可读性差,更具OCD吸引力的形式。
谢谢大家的帮助!
万一有一天有人偶然遇到我同样的问题,我将在完整的解决方案中附加一些示例数据。
从文档:
itertools.groupby
每当键函数的值改变时,它就会产生一个中断或新的组。。。
从这个意义上讲,itertools.groupby
类似于str.split
;区别在于拆分序列也包含在输出中。
"1,2,3".split(",") ==> ["1", "2", "3"]
"1,2,3".splitLikeGroupBy(",") ==> ["1", ",", "2", ",", "3"]
因此,您没有做错任何事情。
另外,我想说您的解决方案很好。
但是,如果您坚持使用itertools.groupby
,请尝试以下操作:
a = [(k, list(g)) for k, g in groupby(data, lambda d: d.get('id') is not None)];
[a[i][1] + a[i+1][1] for i in range(len(a)) if i % 2 == 0]
第一行直接来自您的代码。第二个是一些简单的处理。
建议:
您可能不希望使用单元素词典列表的列表,而要使用多元素词典列表的列表。
也就是说,与其一起使用:
[
[{"id": "id1"}, {"a": "a1"}],
[{"id": "id2"}, {"a": "a2"}], ...
]
您可能要使用此方法:
[
{"id": "id1", "a": "a1"},
{"id": "id2", "a": "a2"}, ...
]
希望这可以帮助。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句