Axel Axel - 5 months ago 12
Ruby Question

How to sort an array of Integer and OpenStruct objects by a key of one of the OpenStruct Keys

I am just learning Ruby and started working with arrays. I have an array that looks like:

easyStats = [<SampleArray: @id=0, @stats=#<OpenStruct total_sessions_played=244, total_sessions_lost=124>>,
<SampleArray: @id=1, @stats=#<OpenStruct total_sessions_played=204, total_sessions_lost=129>>,
<SampleArray: @id=2, @stats=#<OpenStruct total_sessions_played=2, total_sessions_lost=4>>]


I can sort the array by the id (Integer) attribute as such:

easyStats.sort_by(&:id)


However, what I would like to do is sort the array by a key of the OpenStruct object, I have tried the following options with different errors:

easyStats.sort_by(&:stats)



Error: comparison of OpenStruct with OpenStruct failed


easyStats.sort_by(&:stats[:total_sessions_played])



Error: no implicit conversion of Symbol into Integer


easyStats[:stats].sort_by(&:total_sessions_played)



Error: no implicit conversion of Symbol into Integer


I have seen solutions on how to sort an array of just one OpenStruct object and I think I understand it - How to sort a ruby array by two conditions

Could someone show me how to sort by any key of the OpenStruct object in this example (Array with Integer and OpenStruct objects)?

Answer

The sort_by method takes a block and uses the return value of that block as the key to sort by. In your case, you can access that value by doing:

easyStats.sort_by { |i| i.stats.total_sessions_played }

The .sort_by(&:key) code is really just shorthand for .sort_by { |i| i.key }. And you can only use it when the block consists of a single method called on the block argument. You can read more about how and why it works here.