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\$

2 Answers 2

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\$
1
  • \$\begingroup\$ Thanks! It's a thing that popped up from a pet project actually :-) \$\endgroup\$
    – sekmo
    Nov 14, 2018 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 and acknowledge you have read our privacy policy.

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