在字典的列表上执行循环的Python风格方法

5
这段代码是可行的,但我想知道是否有更符合Python语言特点的写法。 word_frequency 是一个字典列表,例如:
word_frequency = {'dogs': [1234, 4321], 'are': [9999, 0000], 'fun': [4389, 3234]}

vocab_frequency = [0, 0] # stores the total times all the words used in each class
for word in word_frequency: # that is not the most elegant solution, but it works!
    vocab_frequency[0] += word_frequency[word][0] #negative class
    vocab_frequency[1] += word_frequency[word][1] #positive class

有没有更优雅的方式来编写这个循环呢?

2
既然你只是用 word_frequency 回溯 word,那么可以直接迭代 word_frequency.values() - pdexter
这里有许多简单而优雅的答案。那么...我想我们可以说“pythonic”意味着同一件事可以用许多整洁的方式完成? - Karl
@Karl Python允许我们编写非常整洁和简洁的代码。然而,如果像我一样,你是在C语言中学习编程的,很多时候你会发现自己创建了消耗资源的循环和函数,这些可以用更加优雅且通常更有效的方式来处理。https://blog.startifact.com/posts/older/what-is-pythonic.html - Victor Zuanazzi
是的,我的帖子只是对此的认可。我试图指出,如果你问一群Python程序员提出“最Pythonic的方式”(这是我经常看到的问题),那么所揭示的Pythonic实际上是Python允许以多种方式使用如此紧凑的习语。 - Karl
9个回答

8

我不确定这是否更符合 Python 风格:

>>> word_frequency = {'dogs': [1234, 4321], 'are': [9999, 0000], 'fun': [4389, 3234]}
>>> vocab_frequency = [sum(x[0] for x in word_frequency.values()),
                       sum(x[1] for x in word_frequency.values())]
>>> print(vocab_frequency)
[15622, 7555]

使用 reduce 的另一种解决方案:

>>> reduce(lambda x, y: [x[0] + y[0], x[1] + y[1]], word_frequency.values())
[15622, 7555]

在我看来,使用for循环的列表推导式更符合Pythonic风格。 - doctorlove

4
你可以使用numpy来实现这个功能:
import numpy as np

word_frequency = {'dogs': [1234, 4321], 'are': [9999, 0000], 'fun': [4389, 3234]}
vocab_frequency = np.sum(list(word_frequency.values()), axis=0)

1
使用numpy就像是杀鸡焉用牛刀:P - SirtusKottus
为什么numpy...就像Sirtuskottus所说的那样-有些过度了。 - NaruS
1
没错,这有点过头了。但是根据上下文,你可能已经导入它了。 - David Speck

2
list(map(sum, zip(*word_frequency.values())))

我认为这是问题的最短解决方案。 - hochl

2

这可能不是解决问题最短的方式,但希望是最易理解的...

word_frequency = {'dogs': [1234, 4321], 'are': [9999, 0000], 'fun': [4389, 3234]}

negative = (v[0] for v in word_frequency.values())
positive = (v[1] for v in word_frequency.values())
vocab_frequency = sum(negative), sum(positive)

print (vocab_frequency)  # (15622, 7555)

虽然更有经验的Python开发者可能更倾向于使用zip来解包这些值:

negative, positive = zip(*word_frequency.values())
vocab_frequency = sum(negative), sum(positive)

1
另一种方法是这样的:

vocab_frequency[0], vocab_frequency[1] = list(sum([word_frequency[elem][i] for elem in word_frequency]) for i in range(2))

print(vocab_frequency[0])
print(vocab_frequency[1])

输出:

15622
7555

然而,还有一种方法可以做到这一点,有点牵强附会,就是这样:

*vocab_frequency, = list(map(sum,zip(*word_frequency.values())))

print(vocab_frequency)

输出:

[15622, 7555]

1
for frequencies in word_frequency.values():
    vocab_frequency = [sum(x) for x in zip(vocab_frequency, frequencies)] 

1
你可以将该字典转换为 pandas DataFrame,这样处理起来会更加简单。
import pandas as pd
word_frequency = {'dogs': [1234, 4321], 'are': [9999, 0000], 'fun': [4389, 3234]}

#Syntax to create DataFrame
df = pd.DataFrame(word_frequency)

#Result
   dogs   are   fun
0  1234  9999  4389
1  4321     0  3234

现在只需将每行相加,然后转换回列表或保留为数据框对象。
#Take sum of each row and convert to list
df = df.sum(axis=1)
df = df.values.tolist()
print(df)

#Output
[15622, 7555]

1
尝试这个单行解决方案:
[sum([word_frequency[i][0] for i in word_frequency]),sum([word_frequency[i][1] for i in word_frequency])]

0
for n, p in your_dict.vales():
    res[0] += n
    res[1] += p

这将足够快速和优雅。
来自手机发送。对于格式不好,敬请谅解。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接