sdawes
sdawes

Reputation: 661

Perform different calculation on each element of an array

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

Answers (4)

nPn
nPn

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

Cary Swoveland
Cary Swoveland

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

Keith Bennett
Keith Bennett

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

Prity
Prity

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

Related Questions