Python 听写理解抛弃元素 从itertools导入groupby 从运算符导入itemgetter d=[{'k':'v1'}] r=k,v代表k,v在groupbyd中,key=itemgetter'k' 对于r中的k,v: printk,listv1[{'k':'v1'}] 打印'--' r={k:v代表k,v在groupbyd中,key=itemgetter'k'} 对于r项中的k、v: printk,listv v1[]
似乎有点怪,还是我遗漏了什么?这是一个关于itertools的讨论。groupby: 返回的组本身是一个迭代器,它与groupby共享底层iterable。因为源是共享的,所以当groupby对象处于高级状态时,上一个组将不再可见。因此,如果以后需要该数据,则应将其存储为列表 换句话说,在获取迭代器中的下一项之前,您需要访问该组-在本例中,是从dict理解内部。要在听写理解中使用它,您需要在理解中列出:Python 听写理解抛弃元素 从itertools导入groupby 从运算符导入itemgetter d=[{'k':'v1'}] r=k,v代表k,v在groupbyd中,key=itemgetter'k' 对于r中的k,v: printk,listv1[{'k':'v1'}] 打印'--' r={k:v代表k,v在groupbyd中,key=itemgetter'k'} 对于r项中的k、v: printk,listv v1[],python,grouping,dictionary-comprehension,Python,Grouping,Dictionary Comprehension,似乎有点怪,还是我遗漏了什么?这是一个关于itertools的讨论。groupby: 返回的组本身是一个迭代器,它与groupby共享底层iterable。因为源是共享的,所以当groupby对象处于高级状态时,上一个组将不再可见。因此,如果以后需要该数据,则应将其存储为列表 换句话说,在获取迭代器中的下一项之前,您需要访问该组-在本例中,是从dict理解内部。要在听写理解中使用它,您需要在理解中列出: from itertools import groupby from operator im
from itertools import groupby
from operator import itemgetter
d = [{'k': 'v1'}]
r = {k: list(v) for k, v in groupby(d, key=itemgetter('k'))}
for k, v in r.items():
print(k, v) # v1 [{'k': 'v1'}]
在第一个示例中,因为您使用的是生成器表达式,所以在启动for循环之前,实际上不会开始迭代groupby迭代器。但是,如果使用非惰性列表理解而不是生成器,则会出现同样的问题,即r=[k,v代表k,v在groupbyd中,key=itemgetter'k']
为什么会这样?
保留惰性迭代是itertools背后的激励思想。因为它处理的可能是大型或无限的迭代器,所以它从不想在内存中存储任何值。它只调用底层迭代器的next,并使用该值执行某些操作。一旦调用了next,就无法返回到以前的值而不存储它们,而itertools不希望这样做
使用groupby,通过示例更容易看到。下面是一个简单的生成器,用于生成正负数的交替范围,以及一个分组它们的groupby迭代器:
def make_groups():
i = 1
while True:
for n in range(1, 10):
print("yielding: ", n*i)
yield n * i
i *= -1
g = make_groups()
grouper = groupby(g, key=lambda x: x>0)
make_groups每次调用next时都会打印一行,然后再生成值以帮助了解发生了什么。当我们在grouper上调用next时,这将导致下一次调用g并得到第一个组和值:
> k, gr = next(grouper)
yielding: 1
现在,对gr的下一次调用都会导致对基础g的下一次调用,正如您从打印中看到的:
> next(gr)
1 # already have this value from the initial next(grouper)
> next(gr)
yielding: 2 # gets the next value and clicks the underlying generator to the next yield
2
现在看看如果我们在grouper上调用next来获得下一个组会发生什么:
> next(grouper)
yielding: 3
yielding: 4
yielding: 5
yielding: 6
yielding: 7
yielding: 8
yielding: 9
yielding: -1
Groupby在生成器中迭代,直到它遇到一个改变键的值。这些值由g。我们不能再计算gr ie.3的下一个值,除非我们以某种方式存储了所有这些值,或者我们以某种方式将底层g生成器t-ed转换为两个独立的生成器。对于默认实现来说,这两种方法都不是好的解决方案,特别是因为itertools的要点不是这样做,所以这要由您来完成,但您需要在调用NextGroup之前存储这些值,并使生成器超过您想要的值。这是itertools的一个优点。groupby:
返回的组本身是一个迭代器,它与groupby共享底层iterable。因为源是共享的,所以当groupby对象处于高级状态时,上一个组将不再可见。因此,如果以后需要该数据,则应将其存储为列表
换句话说,在获取迭代器中的下一项之前,您需要访问该组-在本例中,是从dict理解内部。要在听写理解中使用它,您需要在理解中列出:
from itertools import groupby
from operator import itemgetter
d = [{'k': 'v1'}]
r = {k: list(v) for k, v in groupby(d, key=itemgetter('k'))}
for k, v in r.items():
print(k, v) # v1 [{'k': 'v1'}]
在第一个示例中,因为您使用的是生成器表达式,所以在启动for循环之前,实际上不会开始迭代groupby迭代器。但是,如果使用非惰性列表理解而不是生成器,则会出现同样的问题,即r=[k,v代表k,v在groupbyd中,key=itemgetter'k']
为什么会这样?
保留惰性迭代是itertools背后的激励思想。因为它处理的可能是大型或无限的迭代器,所以它从不想在内存中存储任何值。它只调用底层迭代器的next,并使用该值执行某些操作。一旦调用了next,就无法返回到以前的值而不存储它们,而itertools不希望这样做
使用groupby,通过示例更容易看到。下面是一个简单的生成器,用于生成正负数的交替范围,以及一个分组它们的groupby迭代器:
def make_groups():
i = 1
while True:
for n in range(1, 10):
print("yielding: ", n*i)
yield n * i
i *= -1
g = make_groups()
grouper = groupby(g, key=lambda x: x>0)
make_groups每次调用next时都会打印一行,然后再生成值以帮助了解发生了什么。当我们在grouper上调用next时,这将导致下一次调用g并得到第一个组和值:
> k, gr = next(grouper)
yielding: 1
现在,对gr的下一次调用都会导致对基础g的下一次调用,正如您从打印中看到的:
> next(gr)
1 # already have this value from the initial next(grouper)
> next(gr)
yielding: 2 # gets the next value and clicks the underlying generator to the next yield
2
现在看看如果我们在grouper上调用next来获得下一个组会发生什么:
> next(grouper)
yielding: 3
yielding: 4
yielding: 5
yielding: 6
yielding: 7
yielding: 8
yielding: 9
yielding: -1
Groupby在生成器中迭代,直到它遇到一个改变键的值。这些值由g。我们不能再计算gr ie.3的下一个值,除非我们以某种方式存储了所有这些值,或者我们以某种方式将底层g生成器t-ed转换为两个独立的生成器。奈斯
对于默认实现来说,其中的er是很好的解决方案,特别是因为itertools的要点不是这样做,所以这要由您来完成,但您需要在调用NextGroup之前存储这些值,并将生成器提前到所需的值之前。作为旁白,r=k,v代表k,v代表groupbyd中的k,v,key=itemgetter'k'完全没有意义,它与r=groupbyd相同,key=itemgetter'k'作为旁白,r=k,v代表k,v在groupbyd中,key=itemgetter'k'完全没有意义,它与r=groupbyd相同,key=itemgetter'k'你知道他们为什么这样做吗?另一方面,我查看了文档中的伪代码。它看起来像uuu next uuuu在键匹配丢弃键和值时进行迭代,然后返回一个生成器,该生成器将进行迭代,直到下一个键匹配下一个键的返回值。虽然我可能错过了什么。self.id is id看起来像是在迭代器升级后防止返回值的一种保护,但它在某种程度上是循环条件的一部分。@x-yuri,我已经添加了一些注释,说明了为什么这样做。希望能有帮助。你知道他们为什么这样做吗?另一方面,我查看了文档中的伪代码。它看起来像uuu next uuuu在键匹配丢弃键和值时进行迭代,然后返回一个生成器,该生成器将进行迭代,直到下一个键匹配下一个键的返回值。虽然我可能错过了什么。self.id is id看起来像是在迭代器升级后防止返回值的一种保护,但它在某种程度上是循环条件的一部分。@x-yuri,我已经添加了一些注释,说明了为什么这样做。希望能有帮助。