2017-05-18 2 views
3

En supposant que j'ai deux iterables de chiffres de la même longueurDéballer itérables en utilisant la carte

weights = range(0, 10) 
values = range(0, 100, 10) 

je dois compter la somme pondérée. Je sais que cela peut être fait avec la compréhension de la liste

weighted_sum = sum(weight * value for weight, value in zip(weights, values)) 

Je me demande si cela peut être fait en utilisant map et operator.mul comme

import operator 

weighted_sum = sum(map(operator.mul, zip(weights, values))) 

mais cela donne une erreur

Traceback (most recent call last): 
    File "<input>", line 3, in <module> 
TypeError: op_mul expected 2 arguments, got 1 

donc mon question: existe-t-il un moyen de faire passer les tuples déballés à l'aide de map?

+2

devrait-il pas 'weighted_sum = somme (carte (operator.mul, poids, valeurs)) 'sans le' zip '? Ou, comme indiqué dans la documentation 'map', peut-être que [' itertools.starmap'] (https://docs.python.org/3/library/itertools.html#itertools.starmap) aide –

+0

@TobiasKienzler: merci , cela a fonctionné, vous devriez probablement le poster comme réponse –

+0

Fait, bien que [Rahul suggéré] (https://stackoverflow.com/a/44039847/321973), en utilisant «numpy» est encore mieux –

Répondre

4

map n'a pas besoin du zip, il suffit d'utiliser

weighted_sum = sum(map(operator.mul, weights, values)) 

De map's Documentation

Si d'autres arguments itératifs sont passés, la fonction doit prendre autant d'arguments et être appliquée aux éléments de tous les itérables en parallèle.

également mentionné dans la documentation de map est qu'au lieu que vous pouvez utiliser itertools.starmap au lieu de map pour déjà zip entrée ped.


Comme Rahul hinted at, en utilisant numpy est toujours une bonne idée lorsqu'il s'agit de valeurs numériques, en fait quelque chose comme

import numpy as np 

np.asarray(weights) * values 

devrait déjà faire l'affaire (mais contrairement à map ce nécessite les deux tableaux être de même longueur, tandis que map mapperait la longueur la plus courte).

+0

ce sera génial d'ajouter votre suggestion sur [itertools.starmap] (https://docs.python.org/3/library/itertools.html#itertools.starmap) pour les cas où les itérables étaient déjà 'zip'ped –

+0

@AzatIbrakov Fait :) –

4

Essayez ceci:

>>> import operator 
>>> 
>>> weights = range(0, 10) 
>>> values = range(0, 100, 10) 
>>> sum(map(lambda i:operator.mul(*i), zip(weights, values))) 
2850 

Ou

>>> sum(map(operator.mul, weights, values)) 
2850 
+2

Je suggère d'utiliser le second tentative. –

+0

Le premier semble plutôt compliqué, le second me semble plus pythonique (peut-être parce que je pensais juste la même chose;) –

+0

@TobiasKienzler Ouais, en fait, il n'y a pas besoin d'utiliser 'zip'. La deuxième façon est beaucoup mieux et Pythonic. :) – McGrady

2

Vous pouvez également essayer avec numpy,

In [45]: import numpy as np 

In [46]: sum(map(np.multiply,weights,values)) 
Out[46]: 2850 

Selon Tobias Suggestion de Kienzler,

In [52]: np.sum(np.array(weights) * values) 
Out[52]: 2850 
+3

Bon point, en particulier pour les grandes baies, cela pourrait accélérer les choses. Bien, alors vous pourriez aussi bien convertir les tableaux en nombres entiers et simplement utiliser '*' pour le produit scalaire, qui résume déjà le produit élémentaire de toute façon. –

+0

merci, mais j'en ai besoin pour des tests en projet sans 'numpy', donc ce serait une overkill :-) –