程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

用于累积字典值的Python生成器表达式

发布于2019-10-07 19:32     阅读(1007)     评论(0)     点赞(15)     收藏(0)


生成器表达式抛出大量的元组对,例如。以列表形式:

pairs = [(3, 47), (6, 47), (9, 47), (6, 27), (11, 27), (23, 27), (41, 27), (4, 67), (9, 67), (11, 67), (33, 67)]

对于键对= pair [0]和value = pair [1]的每对配对,我想将此对输入流馈送到字典中,以累加各个键的值。显而易见的解决方案是:

dict_k_v = {}
for pair in pairs:
    try:
        dict_k_v[pair[0]] += pair[1]
    except:
        dict_k_v[pair[0]] = pair[1]

>>> dict_k_v
{33: 67, 3: 47, 4: 67, 6: 74, 9: 114, 11: 94, 41: 27, 23: 27}

但是,这可以通过生成器表达式或不使用for循环的类似构造来实现吗?

编辑

为了明确起见,生成器表达式抛出了大量的元组对:

(3,47),(6,47),(9,47),(6,27),(11,27),(23,27),(41,27),(4,67),(9 ,67),(11,67),(33,67)...

并且我想在生成每个键值对时将其累积到字典中(请参阅Paul McGuire的答案)。对= list []语句是不必要的,对此感到抱歉。对于每对(x,y),x是整数,y可以是整数或十进制/浮点数。

我的生成器表达式的形式为:

((x,y) for y in something() for x in somethingelse())

并希望将每个(x,y)对累积为defaultdict。Hth。


解决方案


为了讨论,下面是一个简单的生成器函数,用于为我们提供一些数据:

from random import randint
def generator1():
    for i in range(10000):
        yield (randint(1,10), randint(1,100))

这是使用Python for循环来消耗生成器并计算每个键值对计数的基本解决方案

from collections import defaultdict

tally = defaultdict(int)
for k,v in generator1():
    tally[k] += v

for k in sorted(tally):
    print k, tally[k]

将打印如下内容:

1 49030
2 51963
3 51396
4 49292
5 51908
6 49481
7 49645
8 49149
9 48523
10 50722

但是我们可以创建一个协程,以接受发送给它的每个键值对,并将它们全部累加到传递给它的defaultdict中:

# define coroutine to update defaultdict for every
# key,value pair sent to it
def tallyAccumulator(t):
    try:
        while True:
            k,v = (yield)
            t[k] += v
    except GeneratorExit:
        pass

我们将使用tally defaultdict初始化协程,并通过向其发送None值使其准备好接受值:

# init coroutine
tally = defaultdict(int)
c = tallyAccumulator(tally)
c.send(None)

我们可以使用for循环或列表推导将所有生成器值发送到协程:

for val in generator1():
    c.send(val)

要么

[c.send(val) for val in generator1()]

但是,相反,我们将使用大小为零的双端队列来处理所有生成器表达式的值,而不会创建不必要的None临时列表:

# create generator expression consumer
from collections import deque
do_all = deque(maxlen=0).extend

# loop thru generator at C speed, instead of Python for-loop speed
do_all(c.send(val) for val in generator1())

现在,我们再次查看这些值:

for k in sorted(tally):
    print k, tally[k]

我们得到另一个类似于第一个列表:

1 52236
2 49139
3 51848
4 51194
5 51275
6 50012
7 51875
8 46013
9 50955
10 52192

在David Beazley的页面上了解有关协程的更多信息:http : //www.dabeaz.com/coroutines/



所属网站分类: 技术文章 > 问答

作者:黑洞官方问答小能手

链接:https://www.pythonheidong.com/blog/article/133147/fe2ee44033e0ff55516a/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

15 0
收藏该文
已收藏

评论内容:(最多支持255个字符)