2016-05-21 20 views
1

Ich habe ein Array. Ich muss für jedes Element eine andere Berechnung durchführen. Ich dachte, ich könnte etwas wie das Folgende tun:Führen Sie verschiedene Berechnungen für jedes Element eines Arrays durch

def calc(a, b, c) 
    arr = [a, b, c] 
    arr.map { |i| (i[0] * 600), (i[1] * 800), (i[2] * 1000) } 
end 

calc(5, 8, 15) 

aber das funktioniert nicht. Wie kann ich verschiedene Berechnungen für jedes Element eines einzelnen Arrays durchführen?

+4

Fühlt sich an wie Sie sind komplizierend - warum nicht '[a * 600, b * 800, c * 1000]' –

+0

@FrederickCheung, ich denke dieser Kommentar sollte eine Antwort sein – Ilya

+1

Was erwarten Sie für die Antwort auf 'calc (5, 8, 15) '? –

Antwort

3

Hier sind einige andere Implementierungen, die hilfreich sein könnten. Indem wir die Multiplizierer in ein Array setzen, können wir zip verwenden, um das Element im Eingangsarray mit dem entsprechenden Multiplikatorwert zu verbinden. Außerdem ist es dadurch einfacher, die Logik weiter zu abstrahieren, indem die Multiplikatorwerte aus der Logik entfernt werden, die die Multiplikation ausführt (in multiply_arrays und transform_arrays).

#!/usr/bin/env ruby 

VALUES = [1, 1, 1] 
MULTIPLIERS = [600, 800, 1000] 

def transform(*values) 
    values.zip(MULTIPLIERS).map { |x, y| x * y } 
end 

def multiply_arrays(array1, array2) 
    array1.zip(array2).map { |n1, n2| n1 * n2 } 
end 

def transform_arrays(array1, array2, method_name) 
    array1.zip(array2).map { |n1, n2| n1.public_send(method_name, n2) } 
end 


p transform(*VALUES)       # [600, 800, 1000] 
p multiply_arrays(VALUES, MULTIPLIERS)   # [600, 800, 1000] 
p transform_arrays(VALUES, MULTIPLIERS, :*) # [600, 800, 1000] 

Wenn die Berechnungen wesentlich verschieden sein müssen (verschiedene Operatoren, Werte, komplexere Logik), als ich ein Array von lambdas betrachten würde mit:

def transform_with_lambdas(values, transforms) 
    values.zip(transforms).map do |value, transform| 
    transform.(value) 
    end 
end 

TRANSFORMS = [ 
    ->(x) { x * 600 }, 
    ->(x) { x + 100 }, 
    ->(x) { x/ 3.0 }, 
] 

p transform_with_lambdas(VALUES, TRANSFORMS) # [600, 101, 0.3333333333333333] 
+0

+1 für den Einsatz von zip und die kurze Form des Aufrufs eines Lambda mit der some_lambda. (Some_arg) - konnte nicht finde die Dokumentation auf diesem Formular, weißt du, wo es dokumentiert ist? – nPn

+1

Wenn Sie sich die API-Dokumentation für 'ProC# call' unter http://ruby-doc.org/core-2.2.0/Proc.html#call ansehen, wird in einem Hinweis darauf hingewiesen, dass" prc.() "Prc aufruft .call() mit den gegebenen Parametern. Es ist eine Syntaxzucker, um "Anruf" zu verbergen. " Ich habe einmal getestet und festgestellt, dass dies funktioniert mit * any * -Objekt, das auf "Call" reagiert, nicht nur ein Proc (einschließlich lambdas). –

+0

Danke, ich sehe es jetzt – nPn

0

Hier ist eine Lösung, die Ihnen verschiedene Operationen auf zwei verschiedenen Operanden anzuwenden helfen:

def calc(first_operand_arr, operator_arr, second_operand_arr) 
    result_arr = [] 
    operator_arr.each_with_index do |o, i| 
    result_arr << (first_operand_arr[i]).method(o).(second_operand_arr[i]) 
    end 
    result_arr 
end 

calc([5, 8, 15], ['+', '-', '*'], [5, 3, 2]) 
0
def calc *arr 
    ops = [600, 800, 1000] 
    arr.map { |x| x * ops.shift } 
end 

calc(5, 8, 15) 
    #=> [3000, 6400, 15000] 

Sie könnten verallgemeinern Dies ist wie folgt:

def calc(*arr) 
    arr.map { |op1, op2, m| op1.send(m, op2) } 
end 

calc [5, 6, :*], [2, 3, :+], [10, 8, :-] 
    #=> [30, 5, 2] 
0

Hier ist eine Option mit einem zweiten Array von Lambda, die beliebige Funktionen o sein können f jeden Eintrag in Ihrem Hauptfeld.

operands = [1.0,2.0,3.0] 

operations = [ 
       ->(e) { e * 10} , 
       ->(e) { e + 10 }, 
       ->(e) { e * e } 
      ] 

results = operands.each_with_index.map { |operand, index| operations[index].call(operand) } 
puts results 

bearbeiten Ich habe gerade bemerken dies eine wirklich eine Variation ist oben auf Keith Bennett Antwort, ich werde es hier lassen, da es anders ist, wie das Lambda aus dem Array abgerufen wird.

+0

Ich denke nicht, dass die Verwendung des Index, um sowohl Wert als auch Operation zu erhalten, hilfreich ist, da es unnötige Komplexität ist, die 'zip' vermeidet. –

Verwandte Themen