为啥 itertools groupby 不能按预期工作? [复制]
Posted
技术标签:
【中文标题】为啥 itertools groupby 不能按预期工作? [复制]【英文标题】:Why doesn't itertools groupby work as expected? [duplicate]为什么 itertools groupby 不能按预期工作? [复制] 【发布时间】:2018-01-30 17:46:39 【问题描述】:我正在尝试将整数列表分成奇数组和偶数组。
>>> from itertools import groupby
>>> L = [1,2,3,4]
>>> grouped = [list(g) for k,g in groupby(L, key=lambda x: x % 2)]
>>> grouped
[[1], [2], [3], [4]]
显然,这不是我想要的。但是,如果我首先使用相同的 lambda 键对 L 进行排序,它会按预期工作:
>>> L.sort(key=lambda x: x % 2)
>>> L
[2, 4, 1, 3]
>>> grouped = [list(g) for k,g in groupby(L, key=lambda x: x % 2)]
>>> grouped
[[2, 4], [1, 3]]
我不明白为什么需要预分类。似乎 groupby 应该遍历列表中的整数,根据键函数为每个整数分配一个值,然后对它们进行分组——不管列表顺序如何。
【问题讨论】:
请先阅读documentation,这样您就知道您所使用的功能实际上应该做什么。 在文档中解释得很清楚:docs.python.org/2/library/itertools.html#itertools.groupby “似乎”为什么会出现?你读过文档吗? 您应该首先按该键对可迭代对象进行排序,然后对其进行分组!喜欢:L = sorted(L,key=lambda x:x%2)
知道了。我以前读过文档并认为我理解了,但显然我没有。这里有一个重点:“每次键函数的值发生变化时,它都会生成一个中断或新组(这就是为什么通常需要使用相同的键函数对数据进行排序的原因)。”在发布我的问题之前,我应该重新阅读此内容。对不起。
【参考方案1】:
itertools.groupby
会将满足关键功能的连续项分组。请参阅下面的 (key, group) 对。注意最后相邻偶数项会发生什么:
>>> from itertools import groupby
>>> lst = [1, 2, 3, 4, 6, 8]
>>> grouped = [(k, list(g)) for k, g in groupby(lst, key=lambda x: x % 2)]
>>> grouped
[(1, [1]), (0, [2]), (1, [3]), (0, [4, 6, 8])]
这里有一些获得偶数组和赔率组的方法:
>>> lst = [1, 2, 3, 4]
# OK, post-process groupby iterator
>>> grouped = [(k, list(g)) for k, g in groupby(lst, key=lambda x: x % 2)]
>>> evens = [x[1][0] for x in grouped if not x[0]]
>>> odds = [x[1][0] for x in grouped if x[0]]
>>> evens, odds
([2, 4], [1, 3])
# Better, pre-"sort"/rearrange iterable then groupby (see comments)
>>> key = lambda x: x % 2
>>> rearranged = sorted(lst, key=key)
>>> evens, odds = [(list(g)) for k, g in groupby(rearranged, key=key)]
>>> evens, odds
([2, 4], [1, 3])
# Even Better, simple list comprehensions
>>> evens, odds = [x for x in lst if not x % 2], [x for x in lst if x % 2]
>>> evens, odds
([2, 4], [1, 3])
有关itertools.groupby
的更多信息,请参阅docs 和此post。
替代品
对于复杂的分组,您可以映射一个函数并在 defaultdict
中收集值。
>>> import collections as ct
>>> def even_odd(elem):
... key = "odd" if elem % 2 else "even"
... return key, elem
>>> dd = ct.defaultdict(list)
>>> for k, v in map(even_odd, range(1, 5)):
... dd[k].append(v)
>>> dd
defaultdict(list, 'even': [2, 4], 'odd': [1, 3])
【讨论】:
【参考方案2】:知道了。我以前读过文档并认为我理解了,但显然我没有。这是重点:
“每次键函数的值发生变化时,它都会生成一个中断或新组(这就是为什么通常需要使用相同的键函数对数据进行排序)。” [强调我的。]
在发布我的问题之前,我应该重新阅读此内容。对不起。
【讨论】:
以上是关于为啥 itertools groupby 不能按预期工作? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
为啥 itertools.groupby 可以将 NaN 分组在列表中而不是 numpy 数组中