Kurt W Kurt W - 1 year ago 43
Ruby Question

Ruby - Sorting of nested array of arrays with integers as strings

I am attempting to perform a sort of the array of arrays below. I am successfully able to perform the actual sort operation using

but I cannot update the original array.

Instead, I am resorting to pushing each modified hash to a new array (
) and then trying to re-integrate/merge it with the original one which I don't think is the right approach for something as simple as sorting string integers... How do I simply sort the below data format? Creating a new object is perfectly acceptable; this does not require an in-place sort operation but either approach is acceptable.

Expected Outcome

My goal is to simply sort ascending the chapter numbers (strings) which are the keys in my hashes. So, for example, Matthew is already in order however Acts should list
first, followed by
. Romans should list
first, followed by
, etc. Most importantly, the order of books (Matthew, Acts, Romans, and Revelation) must remain in tact.

Here's what I've tried:

array = Array.new

data.each do |x|
array << Hash[x.last.sort_by {|k,v| k.to_i }]

# 'array' now contains accurate data that has been sorted but it more difficult to re-merge it than to simply sort the original data

Here's my data:

data = [["Matthew",
{"4"=>[{:book=>"Matthew", :verse=>"18-20", :section=>"new_testament"}],
"22"=>[{:book=>"Matthew", :verse=>"37-38", :section=>"new_testament"}]}],
{"9"=>[{:book=>"Acts", :verse=>"8", :section=>"new_testament"}],
"6"=>[{:book=>"Acts", :verse=>"27-28", :section=>"new_testament"}]}],
{"15"=>[{:book=>"Romans", :verse=>"13A", :section=>"new_testament"}],
"2"=>[{:book=>"Romans", :verse=>"4", :section=>"new_testament"}]}],
{"7"=>[{:book=>"Revelation", :verse=>"9-10", :section=>"new_testament"}],
"2"=>[{:book=>"Revelation", :verse=>"2-5B", :section=>"new_testament"}],
"1"=>[{:book=>"Revelation", :verse=>"9-10", :section=>"new_testament"}]}]]

Answer Source

I think you were just about there... just include the book name in your output.

new_data = []

data.each do |x|
  new_data << [ x[0], Hash[x[1].sort_by{|k,_| k.to_i }] ]