Is there a way to sort so that “Vitamin B12” is no

2019-02-19 12:57发布

问题:

In Ruby on Rails, the default sort order will be

Vitamin A
Vitamin B12
Vitamin B6

Is there a mechanism or quick way so that it will sort by a natural language way so that B6 shows before B12?

回答1:

Try something like:

class Array
  def smart_sort
    sort_by{|s| (' '+s).scan(/(\d+)|(\D+)/).map{|d, s| s || d.to_i}}
  end
end

a = ['Vitamin A', 'Vitamin B12', 'Vitamin B6']
p a.smart_sort

# => ["Vitamin A", "Vitamin B6", "Vitamin B12"]

It sorts alternatively by digits and by non-digits.

b = ['3c17d', '1a34be',  '3x1a', '1b01c', '1a34bb']
p b.smart_sort

# => ["1a34bb", "1a34be", "1b01c", "3c17d", "3x1a"]

This is probably similar to what is done in Windows when sorting the file names within a directory.


Update: A newer version. Doesn't need ' '+, as it is automatically supplied by split. It also removes the redundancy of specifying the complementary \d and \D in the regex.

class Array
  def smart_sort
    sort_by{|s| s.split(/(\d+)/).each_slice(2).flat_map{|s, d| [s, d.to_i]}}
  end
end