Sorting Section Headers in Ruby
What is a good way of sorting section number strings in Ruby. For example:
sections = ["10", "3", "4", "5", "6", "7", "8", "9", "2", "1", "1.1", "1.1.1", "1.1.2"]
# ["1", "1.1开发者_Go百科", "1.1.1", "1.1.2", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
If you have to deal with arbitrarily nested subsections then you could do something like this:
sections = ["10", "3", "4", "5", "6", "7", "8", "9", "2", "1", "1.1", "1.2", "1.2.5"]
sections.sort! { |a,b| a.split('.').map(&:to_i) <=> b.split('.').map(&:to_i) }
That implementation isn't exactly quick due to the repeated split
and map
but you could roll your own Schwartzian Transform if it was too slow:
sections.map { |e| [e, e.split('.').map(&:to_i) ] } \
.sort { |a, b| a.last <=> b.last } \
.map { |e| e.first }
Note that Enumerable#sort_by
does an internal Schwartzian Transform for you:
The current implementation of sort_by generates an array of tuples containing the original collection element and the mapped value.
So you could also let sort_by
take care of some of the ugliness:
section.sort_by { |e| e.split('.').map(&:to_i) }
and get something that is pretty easy to understand at a glance.
If it is possible that you may go to more than two levels, you can do the following:
sections.sort_by{ |section| section.split('.').map(&:to_i)}
Use Enumerable
's sort_by
method:
sections.sort_by(&:to_f)
Or, the slightly longer version:
sections.sort_by{ |section| section.to_f }
IF they are always going to be like that you could cast them to floats..
sections = ["10", "3", "4", "5", "6", "7", "8", "9", "2", "1", "1.1", "1.2"]
=> ["10", "3", "4", "5", "6", "7", "8", "9", "2", "1", "1.1", "1.2"]
sections.sort {|x,y| x.to_f <=> y.to_f}
=> ["1", "1.1", "1.2", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
精彩评论