为啥 itertools.groupby() 不起作用? [复制]
Posted
技术标签:
【中文标题】为啥 itertools.groupby() 不起作用? [复制]【英文标题】:Why itertools.groupby() doesn't work? [duplicate]为什么 itertools.groupby() 不起作用? [复制] 【发布时间】:2018-05-06 10:21:25 【问题描述】:我检查了一些关于 groupby()
的主题,但我不明白我的示例有什么问题:
students = ['name': 'Paul', 'mail': '@gmail.com',
'name': 'Tom', 'mail': '@yahoo.com',
'name': 'Jim', 'mail': 'gmail.com',
'name': 'Jules', 'mail': '@something.com',
'name': 'Gregory', 'mail': '@gmail.com',
'name': 'Kathrin', 'mail': '@something.com']
key_func = lambda student: student['mail']
for key, group in itertools.groupby(students, key=key_func):
print(key)
print(list(group))
这会分别打印每个学生。为什么我没有只得到 3 个组:@gmail.com
、@yahoo.com
和 @something.com
?
【问题讨论】:
Jim 的电子邮件是gmail.com
,而不是像其他人一样的 @gmail.com
。错字?
【参考方案1】:
首先,有些邮件是gmail.com
,有些是@gmail.com
,这就是为什么它们被视为单独的组。
groupby
还期望数据由相同的key
函数预先排序,这解释了为什么您会得到两次@something.com
。
来自docs:
... 通常,iterable 需要已经在相同的 key 函数上排序。 ...
students = ['name': 'Paul', 'mail': '@gmail.com', 'name': 'Tom', 'mail': '@yahoo.com',
'name': 'Jim', 'mail': 'gmail.com', 'name': 'Jules', 'mail': '@something.com',
'name': 'Gregory', 'mail': '@gmail.com', 'name': 'Kathrin', 'mail': '@something.com']
key_func = lambda student: student['mail']
students.sort(key=key_func)
# sorting by same key function we later use with groupby
for key, group in itertools.groupby(students, key=key_func):
print(key)
print(list(group))
# @gmail.com
# ['name': 'Paul', 'mail': '@gmail.com', 'name': 'Gregory', 'mail': '@gmail.com']
# @something.com
# ['name': 'Jules', 'mail': '@something.com', 'name': 'Kathrin', 'mail': '@something.com']
# @yahoo.com
# ['name': 'Tom', 'mail': '@yahoo.com']
# gmail.com
# ['name': 'Jim', 'mail': 'gmail.com']
在修复排序和gmail.com
/@gmail.com
之后,我们得到了预期的输出:
import itertools
students = ['name': 'Paul', 'mail': '@gmail.com', 'name': 'Tom', 'mail': '@yahoo.com',
'name': 'Jim', 'mail': '@gmail.com', 'name': 'Jules', 'mail': '@something.com',
'name': 'Gregory', 'mail': '@gmail.com', 'name': 'Kathrin', 'mail': '@something.com']
key_func = lambda student: student['mail']
students.sort(key=key_func)
for key, group in itertools.groupby(students, key=key_func):
print(key)
print(list(group))
# @gmail.com
# ['mail': '@gmail.com', 'name': 'Paul',
# 'mail': '@gmail.com', 'name': 'Jim',
# 'mail': '@gmail.com', 'name': 'Gregory']
# @something.com
# ['mail': '@something.com', 'name': 'Jules',
# 'mail': '@something.com', 'name': 'Kathrin']
# @yahoo.com
# ['mail': '@yahoo.com', 'name': 'Tom']
【讨论】:
好的,我已经阅读了文档,并且看到必须对序列进行排序,但由于无法对字典进行排序,我迷路了。我创建了一个混乱的代码。 @kviatek 这是关于对字典的列表进行排序,而不是字典本身。 我正在尝试将问题编辑为更合适的重复目标;如果我像其他人一样将 Jim 的电子邮件从gmail.com
更改为 @gmail.com
,您介意吗?这与我认为的问题无关。
@Aran_Fey 是的,当然,我已经看到你已经这样做了,但无论如何我都会回应。 DeepSpace 是的,我知道,但就像我说过的那样,我迷失在所有对象中,最后我试图对字典进行排序,显然,这不是必须要做的。现在一切都清楚了。【参考方案2】:
itertools 使用数据的排序顺序。您的列表未排序。
因此,如果您有 ["gmail.com", "something.com", "gmail.com"],itertools 将创建三个组。这与某些函数式语言中的 groupby 不同(或者 Python pandas)。
您需要先对字典进行排序。
import itertools
students = ['name': 'Paul', 'mail': '@gmail.com', 'name': 'Tom', 'mail': '@yahoo.com',
'name': 'Jim', 'mail': 'gmail.com', 'name': 'Jules', 'mail': '@something.com',
'name': 'Gregory', 'mail': '@gmail.com', 'name': 'Kathrin', 'mail': '@something.com']
for key, group in itertools.groupby(sorted(students, key=lambda x: x["mail"]), key=lambda student: student['mail']):
print(key)
print(list(group))
# @gmail.com
# ['name': 'Paul', 'mail': '@gmail.com', 'name': 'Gregory', 'mail': '@gmail.com']
# @something.com
# ['name': 'Jules', 'mail': '@something.com', 'name': 'Kathrin', 'mail': '@something.com']
# @yahoo.com
#['name': 'Tom', 'mail': '@yahoo.com']
#gmail.com
# ['name': 'Jim', 'mail': 'gmail.com']
【讨论】:
我不是反对者,但是:这与字典不可排序的事实无关,OP 是按字典的 list 分组的。您可以在我的回答中看到为什么它不能按预期工作 谢谢 DeepSpace。固定。以上是关于为啥 itertools.groupby() 不起作用? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
为啥 itertools groupby 不能按预期工作? [复制]