Search code examples
rubysortingfractions

How to best sort a list of strings with fractions in ruby?


Take an existing list of strings with whole and fractions of inch that includes the inch symbol:

['1"','1/2"','1 1/4"','1/4"','2"','1 1/8"']

Is there a best (rubyish, elegant, use of methods, object oriented) way in ruby to sort so it becomes

['1/4"','1/2"','1"','1 1/8"','1 1/4"','2"']


Solution

  • String#to_r will conveniently ignore trailing garbage (such as "):

    The parser ignores leading whitespaces and trailing garbage.

    so converting something like '1 1/2"' to a number that will compare sensibly is a simple matter of:

    s = '1 1/2"'
    r = s.split.map(&:to_r).inject(:+)
    

    Split the string into pieces, convert each to a Rational using String#to_r, and then add them up using Enumerable#inject with a symbol argument. Clean and easy.

    Once you have that, sorting is trivial:

    array        = ['1"','1/2"','1 1/4"','1/4"','2"','1 1/8"']
    rationalized = lambda { |s| s.split.map(&:to_r).inject(:+) }
    sorted       = array.sort_by(&rationalized)
    

    You don't have to use a lambda of course:

    array.sort_by { |s| s.split.map(&:to_r).inject(:+) }
    

    but I find that naming your little snippets of logic clarifies things.