Task: convert this array of hashes:

animals = [
  {"cats" => 3},
  {"dogs" => 5 }

to this hash:

  "cats" => 3,
  "dogs" => 5

This is my solution, any feedback is appreciated :-)

animals.reduce({}) {|m,e|
  e.each{|k,v| m[k] = v}; m
  • 1
    \$\begingroup\$ You've given an example, but can you be more specific about the requirements and constraints? For example, is guaranteed that each element of animals is a Hash with a single entry? Is it guaranteed that there are no duplicates or clashes? \$\endgroup\$ – 200_success Jan 26 '19 at 0:08
  • \$\begingroup\$ no constraints, it just has to work with that example :-) \$\endgroup\$ – sekmo Jan 27 '19 at 23:11

The snippet e.each{|k,v| m[k] = v} does the same thing as the standard library method Hash#merge!, so the shortest way to write your solution is probably:

animals.reduce({}, :merge!)

Note that with this solution, if two hashes in the source array have duplicate keys, those coming later in the array will take priority and overwrite the duplicate keys from earlier in the array:

[{"egrets" => 17}, {"egrets" => 21}].reduce({}, :merge!)  # => {"egrets"=>21}

Also be aware that merge! is destructive to the original hash, which is fine here since we don't reuse the literal input to reduce. There is a non-destructive version, merge, which is better when the input needs to be preserved.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.