Flatten an array of hashes in ruby

33,064

Solution 1

If it's in Rails or if you have to_proc defined, you can go a little bit shorter than @toholio's solution:

arr = [{"fruit_id"=>"1"}, {"fruit_id"=>"2"}, {"fruit_id"=>"3"}]
out = arr.map(&:values).flatten # => ["1", "2", "3"]

Solution 2

So you want each hash to be converted to its values then joined with the values from the other hashes?

in = [{"fruit_id"=>"1"}, {"fruit_id"=>"2"}, {"fruit_id"=>"3"}]
out = in.map{ |item| item.values }.flatten

out will then be ["1","2","3"].

Solution 3

@wombleton @aronchick I suggest to use "flat_map(&:values)" instead "map(&:values).flatten" for better performance.

arr = [{"fruit_id"=>"1"}, {"fruit_id"=>"2"}, {"fruit_id"=>"3"}]
out = arr.flat_map(&:values)

Take a look here for more info: http://gistflow.com/posts/578-use-flat_map-instead-of-map-flatten

Solution 4

if you use map!, you don't create another array in memory

a.map! {|h| h.values}.flatten

this can be also written as

a.map!(&:values).flatten!

also looking at the comments, theres a method in ruby 1.9.3 called flat_map (http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-flat_map) that will do the map and the flatten in one call.

a.flat_map(&:values)

Solution 5

a.inject([]) { |mem,obj| mem += obj.values }
Share:
33,064
aronchick
Author by

aronchick

About me: I've heard containers and Kubernetes are a thing. Are they a thing? Yes. Yes, they are. I now work on machine learning.

Updated on July 09, 2022

Comments

  • aronchick
    aronchick almost 2 years

    I have some simple code that looks like this:

    fruit.each do |c|
      c.each do |key, value|
        puts value
      end
    end
    

    This works fine, but it feels un-ruby like. My goal is to take this array:

    [{"fruit_id"=>"1"}, {"fruit_id"=>"2"}, {"fruit_id"=>"3"}]
    

    And convert it to this:

    [ "1", "2", "3" ]
    

    Thoughts?

  • aronchick
    aronchick almost 15 years
    I wish I could approve both - this is great too!
  • toholio
    toholio almost 15 years
    Well, they're actually the same solution really. :)
  • glenn jackman
    glenn jackman almost 15 years
    injecting into an empty array is also known as collect (or map). see other answers here.
  • glenn jackman
    glenn jackman almost 15 years
    Use << instead of += to append to arrays. It will be slightly faster as you won't be creating all those new array objects.
  • Hemant Kumar
    Hemant Kumar almost 15 years
    << and += are not the same. If you want to use "<<" you will have to flatten again. Anyways its just nitpick.
  • jtzero
    jtzero almost 12 years
    for 1.9.3 there is arr.flat_map(&:values)
  • Taryn East
    Taryn East over 11 years
    ...or at least not use a local variable.