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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.