1
arr1 = [{2=>7}, {2=>3, 8=>1}, {2=>2, 5=>2}]
arr2 = [{2=>9.95, 5=>16.95, 8=>24.95}]

expected result [ 69.65 , 54.8 , 53.8 ]

Here is the calculation:

So arr1 is kind of the map for the second array.

So I need to loop through the array 1 and array 2 then match the key of the array 1 and array 2 then grab the value of array 1 and multiple by the value of array 2.

Now in the array 1 second index there are 2 key value pairs which it means I have to do what I have explained and then then sum up the findings in that hash.

Hope it make sense.

I can do it through lots of loops. Just want to see if there are better ways like using map, etc to be more efficient.

Thank you for your help.

2
  • arr2 is not an array. Either it is badly named or wrong. Can you clarify? Commented Jun 23, 2017 at 8:13
  • You are correct it doesn't need to be an array. I got it wrong. However I better to change it to hash as @vamsi already answer to both of possibilites. Commented Jun 23, 2017 at 8:22

3 Answers 3

4

Assuming your arr2 is actually {2=>9.95, 5=>16.95, 8=>24.95} (because it makes no sense for it to be an array) and renaming it as hash2:

arr1.map { |hash|
  hash.inject(0) { |accu, (key, multiplier)|
    accu + hash2[key] * multiplier
  }
}

EDIT: maybe a bit more understandable (but will only work on Ruby 2.4+):

arr1.map { |hash|
  hash.sum { |key, multiplier|
    hash2[key] * multiplier
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks mate. Your solution is very good however @vamsi solution is easier to understand. Thanks again for your help
sum can be used with a block, i.e. hash.sum { |k, m| hash2[k] * m }
Thanks again, @Stefan. I really should read those new docs more carefully :)
3

As per your question,

arr1.map{|a1| a1.keys.map{|a1k| arr2[0][a1k]*a1[a1k]}.inject(:+)}

If arr2 is just a simple hash:

arr1.map{|a1| a1.keys.map{|a1k| arr2[a1k]*a1[a1k]}.inject(:+)}

1 Comment

Thank mate that was simple. I should have thought outside the box and map the keys. Did not think like that. Thanks
1

As we need to compute one inner product for each element of arr1, we can use matrix multiplication.

arr = [{2=>7}, {2=>3, 8=>1}, {2=>2, 5=>2}]
h = {2=>9.95, 5=>16.95, 8=>24.95}

require 'matrix'

keys, values = h.to_a.transpose
  #=> [[2, 5, 8], [9.95, 16.95, 24.95]]

(Matrix[*arr.map { |g| keys.map { |k| g.fetch(k,0) } }] *
  Matrix.column_vector(values)).to_a.flatten
  #=> [69.64999999999999, 54.8, 53.8]

Note that

arr.map { |g| keys.map { |k| g.fetch(k,0) } }
  #=> [[7, 0, 0], [3, 0, 1], [2, 2, 0]]

See Matrix and Hash#fetch.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.