2008-08-06 6 views
18

Ich frage mich, ob es einen Weg gibt, zu tun, was ich kann mit Python unten tun, in Ruby:Mapping Werte von zwei Array in Ruby

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

Ich habe zwei Arrays gleicher Größe mit den Gewichten und Daten aber ich kann nicht scheinen, eine Funktion ähnlich Karte in Ruby zu finden, reduziere ich arbeite.

Antwort

13

@Michiel de Mare

Ihr Ruby 1.9 Beispiel kann ein bisschen weiter verkürzt werden:

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

Beachten Sie auch, dass in Ruby 1.8, wenn Sie Active (von Rails) benötigen, können Sie verwenden:

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

Das ist nicht für mich arbeiten Ruby 1.9.3 (Argument.): '[1,2,3] .zip ([4,5,6]) Karte (: *) ' –

+0

@Fe lixRabe: Es scheint, dass Ruby geändert hat, wie die Argumente in dieser Art von Proc behandelt werden. Ich kenne keine Details, da ich in ein paar Jahren Ruby nicht berührt habe. –

1

Die Funktion Array.zip verwendet eine elementweise Kombination von Arrays. Es ist nicht ganz so sauber wie die Python-Syntax, aber hier ist ein Ansatz, den Sie verwenden:

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 hat eine map Methode (auch bekannt als die collect-Methode), die für jedes Enumerable Objekt angewandt werden kann. Wenn numbers eine Anordnung von Zahlen ist, die folgende Zeile in Ruby:

numbers.map{|x| x + 5} 

ist die äquivalent zu der folgenden Zeile in Python:

map(lambda x: x + 5, numbers) 

Für weitere Einzelheiten siehe here oder here.

5

In Ruby 1.9:

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

In Ruby 1.8:

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

Eine Alternative für die Karte, die auch für mehr als 2 Arrays funktioniert:

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} 

Dies auch hinzugefügt werden könnten, um Array:

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