>>from itertools import groupby >>keyfunc = lambda x : x > 500 >>obj = dict(groupby(range(1000), keyfunc)) >>list(obj[True]) [999] >>list(obj[False]) []
范围(x> 500)默认情况下对范围(1000)进行排序。 我期待从0到999的数字按条件(x> 500)分组在dict中。但由此产生的字典只有999。 其他数字在哪里?谁能解释一下这里发生了什么?
来自docs:
返回的组本身是一个迭代器,它与
groupby()
共享底层迭代。由于源是共享的,因此当groupby()
对象前进时,前一组不再可见。因此,如果以后需要该数据,则应将其存储为列表[。]
并且您将在obj
中存储迭代器并在以后实现它们。
In [21]: dict((k, list(g)) for k, g in groupby(range(10), lambda x : x > 5))
Out[21]: {False: [0, 1, 2, 3, 4, 5], True: [6, 7, 8, 9]}
groupby
迭代器返回分组函数结果的元组和一个新的迭代器,它与groupby
运算符正在处理的相同“外部”迭代器相关联。当你将dict()
应用于由groupby
返回的迭代器而不使用这个“内部”迭代器时,groupby
将不得不为你推进“外部”迭代器。您必须意识到groupby
函数不会对序列起作用,它会将任何此类序列转换为迭代器。
也许用一些比喻和手工操作可以更好地解释这一点。请跟随我们形成一条铲斗线。
想象一下,迭代器是一个人从井中抽水桶的人。他有无限数量的桶可供使用,但井可能是有限的。每当你向这个人要一桶水时,他会从水井中抽出一个新桶并将它传递给你。
在groupby
案例中,您将另一个人插入到您的萌芽桶链中。这个人根本没有立即通过水桶。每次你要求一个水桶时,他会把你给它的指示结果和另一个人传给你,然后他会通过groupby
人向你传递水桶给任何人,只要他们与指示相同的结果。如果指令的结果发生变化,groupby
铲斗传球将停止传递这些铲斗。因此,well
向groupby
提供了桶,group A
将此传递给了一个每组人,group B
,groupby
,等等。
在您的示例中,水是编号的,但是从井中只能抽出1000个水桶。以下是当你将dict()
人传递给dict()
电话时会发生什么:
groupby
打电话问groupby
一桶。现在,dict()
要求井上人员提供一个水桶,记得给出的指示结果,坚持到水桶。对于False
,他将通过指令的结果(group A
)加上一个新人group A
。结果存储为键,并且想要拉桶的dict()
人被存储为值。然而,这个人还没有要求桶,因为没有人要求它。groupby
电话要求groupby
换另一个桶。 groupby
有这些说明,并寻找结果发生变化的下一个桶。它仍然坚持着第一个水桶,没有人要求它,所以它扔掉了这个水桶。相反,它要求井中的下一个桶并使用他的指令。结果和以前一样,所以它也抛弃了这个新桶!更多的水流过地板,所以下一个499桶。只有当数量为501的桶通过才会改变结果,所以现在group B
找到另一个人给(人True
)指示,连同新结果dict()
,将这两个传递给dict()
。True
电话存储group B
作为关键,人group B
作为价值。 dict()
什么都不做,没有人要求它换水。groupby
要求另一个桶。 groupby
溢出更多的水,直到它拿着数量为999的水桶,井里的人耸了耸肩,说现在井已空了。 dict()
告诉dict()
这个井是空的,没有更多的水桶即将来临,他可以随便停止询问。它仍然保持数量为999的铲斗,因为它永远不必为井中的下一个铲斗腾出空间。True
与关键group B
相关的事情,这是人group B
。你将list()
传递给group B
,因此将向group B
询问group B
可以得到的所有桶。 groupby
回到group B
,他只拥有一个水桶,数量为999的水桶,这个水桶的指示结果与group B
正在寻找的相符。所以这一桶list()
给了groupby
,然后耸了耸肩,因为没有更多的桶,因为dict()
告诉他。False
与关键group A
相关联的人,即人groupby
。到目前为止,list()
已经没有任何东西可以提供了,井是干燥的,他站在一滩999桶水中,数字漂浮在周围。你的第二个groupby
什么都没得到。这个故事的寓意?在与>>> from itertools import groupby
>>> keyfunc = lambda x : x > 5
>>> obj = dict((k, list(v)) for k, v in groupby(range(10), keyfunc))
>>> obj(True)
[0, 1, 2, 3, 4, 5]
>>> obj(False)
[6, 7, 8, 9]
交谈时,立即要求所有水桶,因为如果你不这样做,他会把所有水都洒掉!迭代器就像幻想曲中的扫帚,在没有理解的情况下勤奋地移动水,如果你不知道如何控制它们,你最好希望你用完水。
这里的代码可以达到您的预期(使用少量水来防止泛滥):
range(1000)
你缺少的是,groupby函数迭代你给定的999
,从而返回1000个值。你只保存最后一个,在你的情况下dictionary = {}
keyfunc = lambda x : x > 500
for k, g in groupby(range(1000), keyfunc):
dictionary[k] = list(g)
。你要做的是迭代返回值并将它们保存到你的字典中:
{False: [0, 1, 2, ...], True: [501, 502, 503, ...]}
所以你会得到预期的输出:
itertools groupby
有关更多信息,请参阅有关qazxswpoi的Python文档。