2016-05-21 6 views
1

У меня есть массив. Мне нужно выполнить другой расчет для каждого элемента. Я думал, что смогу сделать что-нибудь вроде:Выполнение различных вычислений для каждого элемента массива

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) 

но это не работает. Как я могу выполнять разные вычисления для каждого элемента одного массива?

+4

Чувства, подобные вам, усложняют - почему бы не '[a * 600, b * 800, c * 1000]' –

+0

@FrederickCheung, я думаю, что этот комментарий должен быть ответом – Ilya

+1

Что вы ожидаете от ответа на 'calc (5, 8, 15) '? –

ответ

3

Вот некоторые другие реализации, которые могут быть полезны. Помещая мультипликаторы в массив, мы можем использовать zip для соединения элемента во входном массиве с соответствующим значением множителя. Кроме того, это упрощает абстрактную логику, удаляя значения множителя из логики, которая делает умножение (в multiply_arrays и 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] 

Если расчеты должны существенно отличаться (разные операторы, ценности, более сложная логика), чем я бы рассмотреть возможность использования массива лямбды:

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 для демонстрации использования zip и короткой формы вызова лямбды с помощью some_lambda. (Some_arg) - не удалось найти документацию на эту форму, знаете ли вы, было ли это документировано? – nPn

+1

Если вы посмотрите на документы API для 'ProC# call' по адресу http://ruby-doc.org/core-2.2.0/Proc.html#call, у него есть примечание, в котором говорится:« Обратите внимание, что prc.() Вызывает prc .call() с указанными параметрами. Это синтаксический сахар, чтобы скрыть «вызов». Я когда-то тестировал и обнаружил, что это будет работать с * любым * объектом, который отвечает на 'call', а не только с Proc (включая lambdas). –

+0

Спасибо, я вижу это сейчас – nPn

0

Вот решение, которое поможет вам применять различные операции на двух разных операндами:

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] 

Вы могли бы обобщать это следующим образом:

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

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

Здесь можно использовать второй массив лямбда, который может быть произвольным функциям o f каждая запись в вашем основном массиве.

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 

Редактировать Я только заметил, что это действительно вариация на ответ Кит Беннетта выше, я оставлю его здесь, так как он отличается, как лямбда извлекается из массива.

+0

Я не думаю, что использование индекса для получения значения и операции полезно, так как это ненужная сложность, которую 'zip' избегает. –