2009-06-17 11 views
11

Come si esegue somma vettoriale in Ruby in modo cheCome si esegue l'aggiunta del vettore in Ruby?

[100, 100] + [2, 3] 

cede

[102, 103] 

(invece di unirsi due array)?

Oppure può essere un altro operatore anche, come

[100, 100] @ [2, 3] 

o

[100, 100] & [2, 3] 
+0

Se questa fosse la chiarezza, la soluzione sarebbe utilizzare la mappa: (map + '(100 100)' (2 3)) => (102 103). Forse Ruby ha una funzione simile? –

risposta

32

Vedere la classe Vector:

require "matrix" 

x = Vector[100, 100] 
y = Vector[2, 3] 
print x + y 

E:\Home> ruby t.rb 
Vector[102, 103] 

Vedi vectorops per ulteriori operazioni su vettori:

& hellip; le seguenti operazioni funzionano come previsto

v1 = Vector[1,1,1,0,0,0] 
    v2 = Vector[1,1,1,1,1,1] 

    v1[0..3] 
    # -> Vector[1,1,1] 

    v1 += v2 
    # -> v1 == Vector[2,2,2,1,1,1] 

    v1[0..3] += v2[0..3] 
    # -> v1 == Vector[2,2,2,0,0,0] 

    v1 + 2 
    # -> Vector[3,3,3,1,1,1] 

Vedi anche vectorops.

3

Oppure, se si vuole un comportamento arbitrario dimensione di tale varietà (come somma vettoriale matematica)

class Vector < Array 
    def +(other) 
    case other 
    when Array 
     raise "Incorrect Dimensions" unless self.size == other.size 
     other = other.dup 
     self.class.new(map{|i| i + other.shift}) 
    else 
     super 
    end 
    end 
end 

class Array 
    def to_vector 
    Vector.new(self) 
    end 
end 

[100,100].to_vector + [2,3] #=> [102,103] 

La mancanza di una mappa in stile lisp è abbastanza odiosa.

18

Array # zip:

$ irb 
irb(main):001:0> [100,100].zip([2,3]).map { |e| e.first + e.last } 
=> [102, 103] 

Shorter:

irb(main):002:0> [100,100].zip([2,3]).map { |x,y| x + y } 
=> [102, 103] 

generalizzato a> 2 dimensioni con #inject:

irb(main):003:0> [100,100,100].zip([2,3,4]).map { |z| z.inject(&:+) } 
=> [102, 103, 104] 
0
module PixelAddition 
    def +(other) 
    zip(other).map {|num| num[0]+num[1]} 
    end 
end 

Quindi è possibile creare un array sottoclasse che si mescola nel modulo o aggiungi il comportamento di array specifici come:

class <<an_array 
    include PixelAddition 
end 
+1

Grande uso dei moduli, ma avendo alcune istanze di Array interpreta l'operatore + in un modo diverso rispetto ad altri casi mi fa davvero paura. Potresti anche ottenere situazioni in cui (a + b)! = (B + a). – molf

3

Quando a Roma..monkeypatch.

module Enumerable 
    def sum 
    inject &:+ 
    end 

    def vector_add(*others) 
    zip(*others).collect &:sum 
    end 
end 

Quindi si può fare a.vector_add (b) e funziona. Credo che questo richieda Ruby 1.8.7, o un'estensione che aggiunge Symbol.to_proc. Puoi anche aggiungere un numero arbitrario di vettori in questo modo.

2

Proprio come un sidenote, se tu (come me) ti sentissi insoddisfatto delle operazioni fornite dalla classe Vector predefinita da ruby, considera l'aspetto del mio gioiello https://github.com/psorowka/vectorops, che aggiunge alcune funzionalità che mi aspetto da un vettore corretto implementazione.

Problemi correlati