首页 > 解决方案 > 广播/迭代字典值的有效方法

问题描述

我正在尝试在这样的计算中使用字典值:

mydict = dict(zip(['key1', 'key2', 'key3'],
                  [1, 2, 3]))
print(mydict)

newvals = (mydict.values() + 3) ** 2
print(newvals)
{'key1': 1, 'key2': 2, 'key3': 3}
TypeError: unsupported operand type(s) for +: 'dict_values' and 'int'

或者如果我这样做,

import numpy as np
newvals = (np.array(mydict.values()) + 3) ** 2
print(newvals)
TypeError: unsupported operand type(s) for +: 'dict_values' and 'int'

看来我必须先将字典值转换为列表,或者使用列表理解进行迭代。

newvals = (np.array(list(mydict.values())) + 3) ** 2
print(newvals)
[16 25 36]

或者我可以

newvals = np.array([(val + 3) ** 2 for val in mydict.values()])
print(newvals)
[16 25 36]

有没有更简单或更有效的方法来做到这一点?或者是否有一种我可以使用的内置字典方法,这样我就不必使用列表理解或 for 循环?

谢谢你。

标签: pythonnumpydictionary

解决方案


当我们谈论避免循环时numpy,我们的实际意思是避免 Python 级别的循环。我们仍然需要循环遍历数组元素,但我们是在快速编译的代码中完成的。该代码仅适用于numpy ndarrays. 此外,通过数组的循环比通过列表的循环更糟糕。

如果我们从列表开始,我们必须首先将其转换为ndarray,例如arr = np.array([1,2,3])。该数组转换需要时间,足以使执行列表理解通常更快。

numpy没有任何代码可以直接使用 Python dictsvalues()制作一个类似生成器的对象。 np.array(...)需要一个类似对象的列表:

In [140]: np.array(list(mydict.values()))                                                      
Out[140]: array([1, 2, 3])
In [141]: (np.array(list(mydict.values())) +3)**2                                              
Out[141]: array([16, 25, 36])

fromiter可以从values对象工作:

In [142]: np.fromiter(mydict.values(), int)                                                    
Out[142]: array([1, 2, 3])

np.fromiter可能比 快np.array,但我不会保证。

我怀疑列表理解更快,尤其是对于这个小例子:

In [143]: [(x+3)**2 for x in mydict.values()]                                                  
Out[143]: [16, 25, 36]

我们可以做一些时间测试,但对于这个小样本,它可能不会那么有用。

字典对很多事情都很有用,但快速数字计算不是其中之一。


推荐阅读