Reputation: 11
I need to sort a multidimensional array by first line. The first line (array[0][0] to array[0][n-1]) is composed of strings, I need to sort it, and the other lines to follow up...
I already searched a lot and saw how to use the sort function to sort it by column, but didn't found out how to apply it to my problem...
I already solved my problem with a bubble sort who sort the first line, then report the change to the other lines if there's one, but I wondered if there was a better way to do it ?
Creation of the array :
array = Array.new(4) { Array.new(var, 0) }
I have something like that in it :
[ [ "A 1", "A 3", "A 2", "A 4" ],
[ 4, 5, 6, 7 ],
[ 2, 2, 2, 2 ],
[ 0.1, 0.2, 0.1, 0.2 ] ]
The expected result would be as followed :
[ [ "A 1", "A 2", "A 3", "A 4" ],
[ 4, 6, 5, 7 ],
[ 2, 2, 2, 2 ],
[ 0.1, 0.1, 0.2, 0.2 ] ]
Upvotes: 0
Views: 486
Reputation: 5313
Less Ruby'ish approach:
sorted = arr.first.sort
# => ["A 1", "A 2", "A 3", "A 4"]
order_arr = arr.first.map { |x| sorted.index(x) }
# => [0, 2, 1, 3]
arr.map { |a| order_arr.map { |x| a[x] } }
# => [["A 1", "A 2", "A 3", "A 4"],
# [4, 6, 5, 7],
# [2, 2, 2, 2],
# [0.1, 0.1, 0.2, 0.2]]
Upvotes: 0
Reputation: 29318
You can use Array#transpose
and Enumerable#sort_by
to handle this like so:
arr = [ [ "A 1", "A 3", "A 2", "A 4" ],
[ 4, 5, 6, 7 ],
[ 2, 2, 2, 2 ],
[ 0.1, 0.2, 0.1, 0.2 ] ]
Array#transpose
turns rows into columns:
arr.transpose
#=> [["A 1", 4, 2, 0.1],
# ["A 3", 5, 2, 0.2],
# ["A 2", 6, 2, 0.1],
# ["A 4", 7, 2, 0.2]]
Then we just need to sort by the first column values sort_by(&:first)
:
arr.transpose.sort_by(&:first)
#=> [["A 1", 4, 2, 0.1],
# ["A 2", 6, 2, 0.1],
# ["A 3", 5, 2, 0.2],
# ["A 4", 7, 2, 0.2]]
Then we just transpose
back again:
arr.transpose.sort_by(&:first).transpose
#=> [["A 1", "A 2", "A 3", "A 4"],
# [4, 6, 5, 7],
# [2, 2, 2, 2],
# [0.1, 0.1, 0.2, 0.2]]
The same could be achieved by zipping the Array
s together like so: (but the former seems like a better choice)
arr.reduce(&:zip).sort_by {|a| a.flatten!.first}.transpose
#=> [["A 1", "A 2", "A 3", "A 4"],
# [4, 6, 5, 7],
# [2, 2, 2, 2],
# [0.1, 0.1, 0.2, 0.2]]
Upvotes: 2