2008-08-06 9 views
18

Je me demande s'il y a un moyen de faire ce que je peux faire ci-dessous avec Python, Ruby:valeurs de mappage de tableau à deux en Ruby

sum = reduce(lambda x, y: x + y, map(lambda x, y: x * y, weights, data)) 

J'ai deux tableaux de tailles égales avec les poids et les données mais je n'arrive pas à trouver une fonction similaire à celle de Ruby, réduire je travaille.

Répondre

13

@Michiel de Mare

Votre exemple Ruby 1.9 peut être raccourci un peu plus loin:

weights.zip(data).map(:*).reduce(:+) 

Notez également que dans Ruby 1.8, si vous avez besoin ActiveSupport (de Rails) vous pouvez utiliser:

weights.zip(data).map(&:*).reduce(&:+) 
+0

qui ne fonctionne pas pour moi sur Ruby 1.9.3 (ArgumentError): '[1,2,3] .zip ([4,5,6]) carte (.: *) ' –

+0

@Fe lixRabe: Il semble que ruby ​​a changé la manière dont les arguments sont traités dans ce type de proc. Je ne connais pas vraiment les détails, puisque je n'ai pas touché de rubis depuis quelques années. –

1

La fonction Array.zip effectue une combinaison élémentaire de tableaux. Il est pas tout à fait aussi propre que la syntaxe de Python, mais voici une approche que vous pouvez utiliser:

weights = [1, 2, 3] 
data = [4, 5, 6] 
result = Array.new 
a.zip(b) { |x, y| result << x * y } # For just the one operation 

sum = 0 
a.zip(b) { |x, y| sum += x * y } # For both operations 
1

Ruby a une méthode map (la méthode collect a.k.a.), qui peut être appliquée à tout objet Enumerable. Si numbers est un tableau de nombres, la ligne suivante dans Ruby:

numbers.map{|x| x + 5} 

est l'équivalent de la ligne suivante en Python:

map(lambda x: x + 5, numbers) 

Pour plus de détails, voir here ou here.

5

Dans Ruby 1.9:

weights.zip(data).map{|a,b| a*b}.reduce(:+) 

Dans Ruby 1.8:

weights.zip(data).inject(0) {|sum,(w,d)| sum + w*d } 
0

Une alternative pour la carte qui fonctionne depuis plus de 2 tableaux ainsi:

def dot(*arrays) 
    arrays.transpose.map {|vals| yield vals} 
end 

dot(weights,data) {|a,b| a*b} 

# OR, if you have a third array 

dot(weights,data,offsets) {|a,b,c| (a*b)+c} 

Cela pourrait aussi être ajouté à tableau:

class Array 
    def dot 
    self.transpose.map{|vals| yield vals} 
    end 
end 

[weights,data].dot {|a,b| a*b} 

#OR 

[weights,data,offsets].dot {|a,b,c| (a*b)+c} 
0
weights = [1,2,3] 
data = [10,50,30] 

require 'matrix' 
Vector[*weights].inner_product Vector[*data] # => 200 
Questions connexes