1
\$\begingroup\$

Problem: convert this array of hashes:

cars = [
  { :model=>"Ferrari 458", :speed=>320 },
  { :model=>"Maserati MC12", :speed=>330 },
  { :model=>"Ferrari Enzo", :speed=>350 },
  { :model=>"Lamborghini Huracan", :speed=>325 }
]

to this data structure:

{
  above_320: [
    { :model=>"Maserati MC12", :speed=>330 },
    { :model=>"Lamborghini Huracan", :speed=>325 },
    { :model=>"Ferrari Enzo", :speed=>350 }
  ],
  the_rest: [
    { :model=>"Ferrari 458", :speed=>320 }
  ]
}

My solution:

cars.partition {|car| car[:speed] > 320}
.map.with_index {|cars,i| [ i == 0 ? :above_320 : :the_rest, cars ]}
.to_h

Any feedback would be greatly appreciated!

\$\endgroup\$
3
\$\begingroup\$

I would go with the chunk method:

cars.chunk { |c| c[:speed]>320 ? :above_320 : :the_rest }.to_h

Though it's important to underline that chunk doesn't work if the array is not ordered (by speed in this case). In that case we need to prepend it with sort_by:

cars.sort_by {|car| car[:speed]}.chunk { |c| c[:speed]>320 ? :above_320 : :the_rest }.to_h

(Moreover, if we want to order the hash keys, like in the example, we need to call sort after chunk):

cars.sort_by {|car| car[:speed]}.chunk { |c| c[:speed]>320 ? :above_320 : :the_rest }.sort.to_h
\$\endgroup\$
  • \$\begingroup\$ Thanks! It's a thing that popped up from a pet project actually :-) \$\endgroup\$ – sekmo Nov 14 '18 at 9:55
2
\$\begingroup\$

I think that .map.with_index {|cars,i| [ i == 0 ? :above_320 : :the_rest, cars ]} is a bit more verbose and awkward than it needs to be.

Hash[
  [:above_320, :the_rest].zip(cars.partition { |car| car[:speed] > 320 })
]

Alternatively,

[:above_320, :the_rest]
  .zip(cars.partition { |car| car[:speed] > 320 })
  .to_h
\$\endgroup\$

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.