Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a natural_sort_by method for Ruby?

I have a list of files with a bunch of attributes. One of the attributes is the file name which is how I would like to sort the list. However, the list goes something like this: filename 1, filename 2, filename 10, filename 20.

The ruby sort_by method produces this:

files = files.sort_by { |file| file.name }
=> [filename 1, filename 10, filename 2, filename 20]

I would like a more human readable list like filename 1, filename 2, filename 10, filename 20

I found the natural_sort gem but it seems to only work like the sort method. I need something where I can specify what to sort the array by.

Any help?

like image 348
Nate Bird Avatar asked Nov 02 '10 14:11

Nate Bird


2 Answers

Here's another take on a "natural" sort method:

class String
  def naturalized
    scan(/[^\d\.]+|[\d\.]+/).collect { |f| f.match(/\d+(\.\d+)?/) ? f.to_f : f }
  end
end

This converts something like "Filename 10" into a simple array with floats in place of numbers [ "Filename", 10.0 ]

You can use this on your list:

files.sort_by! { |file| file.name.to_s.naturalized }

This has the advantage of working on arbitrary numbers in unpredictable positions. The paranoid .to_s call in that block is to ensure that there is a string and not an inadvertent nil when sorting.

like image 158
tadman Avatar answered Oct 26 '22 00:10

tadman


generic answer for strings natural sort

array.sort_by {|e| e.split(/(\d+)/).map {|a| a =~ /\d+/ ? a.to_i : a }}
like image 22
shurikk Avatar answered Oct 25 '22 22:10

shurikk