Reputation: 661
I have an array. I need to perform a different calculation on each element. I thought I could do something like the following:
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)
but this does not work. How can I perform different calculations on each element of a single array?
Upvotes: 1
Views: 133
Reputation: 16738
Here is an option using a second array of lambda's that can be arbitrary functions of each entry in your main array.
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
Edit I just noticed this is a really a variation on Keith Bennett's answer above, I will leave it here, since it is different in how the lambda is retrieved from the array.
Upvotes: 0
Reputation: 110685
def calc *arr
ops = [600, 800, 1000]
arr.map { |x| x * ops.shift }
end
calc(5, 8, 15)
#=> [3000, 6400, 15000]
You could generalize this as follows:
def calc(*arr)
arr.map { |op1, op2, m| op1.send(m, op2) }
end
calc [5, 6, :*], [2, 3, :+], [10, 8, :-]
#=> [30, 5, 2]
Upvotes: 0
Reputation: 4970
Here are some other implementations that might be helpful. By putting the multipliers into an array, we can use zip
to connect the element in the input array with the appropriate multiplier value. In addition, that makes it simple to abstract the logic further by removing the multiplier values from the logic that does the multiplication (in multiply_arrays
and 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]
If the calculations need to be substantially different (different operators, values, more complex logic), than I'd consider using an array of lambdas:
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]
Upvotes: 3
Reputation: 224
Here is a solution which will help you to apply different operations on two different operands:
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])
Upvotes: 0