2009-06-17 11 views
11

Jak wykonać dodawanie wektorów w Ruby, tak abyJak mogę dodać wektor w Ruby?

[100, 100] + [2, 3] 

daje

[102, 103] 

(zamiast łączenia dwóch tablic)?

Albo może to być inny operator zbyt, takich jak

[100, 100] @ [2, 3] 

lub

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

Jeśli to było seplenienie, rozwiązaniem byłoby użycie mapy: (mapa + '(100 100)' (2 3)) => (102 103). Może Ruby ma podobną funkcję? –

Odpowiedz

32

Zobacz klasę Vector:

require "matrix" 

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

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

Zobacz vectorops dodatkowych operacji na wektorach:

& hellip; następujące operacje działają jak oczekiwano

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] 

Zobacz także vectorops.

3

Albo jeśli chcesz arbitralnego zachowania wymiaru tej odmiany (jak matematycznej Ponadto wektor)

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] 

Brak mapy stylu seplenienia jest dość nieprzyjemny.

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] 

uogólnić na> 2 wymiarach z #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 

Następnie można utworzyć tablicę podklasa, która miesza się w module lub dodaje zachowanie się poszczególnych tablic, takich jak:

class <<an_array 
    include PixelAddition 
end 
+1

Wielkie użycie modułów, ale posiadanie niektórych instancji Array interpretuje operatora + w inny sposób niż w innych instancjach naprawdę mnie przeraża. Możesz nawet otrzymać sytuacje, w których (a + b)! = (B + a). – molf

3

Podczas pobytu w Rzymie.monkeypatch.

module Enumerable 
    def sum 
    inject &:+ 
    end 

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

Następnie można zrobić a.vector_add (b) i to działa. Wierzę, że wymaga to Ruby 1.8.7, lub rozszerzenia, które dodaje Symbol.to_proc. Możesz również dodać dowolną liczbę wektorów w ten sposób.

2

Tak jak sidenote, jeśli (podobnie jak ja) czułeś się niezadowolony z operacji dostarczanych przez domyślną klasę Vector z ruby, rozważ nadanie mojemu klejnotowi https://github.com/psorowka/vectorops wyglądu, który dodaje nieco funkcjonalności, której mógłbym oczekiwać od odpowiedniego wektora realizacja.