Why I dig Ruby, part 1

July 25th, 2006

I really like Ruby. For example, a project needed a system to sort version number strings like “3.1.41”. First I converted a recipe to Ruby, resulting in the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class String
  def isdigit?
    self =~ /^[0-9]+$/     
  end
end

def sorted_copy(alist)
    alist.map {|i| _generate_index(i) }.zip(alist).sort.collect {|i,j| j}
end

# Split a string into alpha and numeric elements, which
# is used as an index for sorting
def _generate_index(str)
    # indices is built progressively using _append function
    indices = []
    def _append(fragment, alist)
        fragment = fragment.to_i if fragment.isdigit?
        alist << fragment
    end
    
    # initialize loop
    prev_isdigit = str[0,1].isdigit?
    current_fragment = ''
    # group string into digit and non-digit parts
    str.split(//).each do |char|
        if char.isdigit? == prev_isdigit
            current_fragment += char
        else
            _append(current_fragment, indices)
            current_fragment = char
            prev_isdigit = char.isdigit?
        end
    end
    _append(current_fragment, indices)    
end

def _test
    a = ['1.0.1', '1.0.2', '1.0.1.9', '1.0.10', '1.1.11', '1.0.921']
    p sorted_copy(a)
end

if __FILE__ == $0
    _test()
end

However, this is not too elegant, and we could take advantage of Ruby’s
sort_by. Also, version numbers of the form ‘v1.2.3’ will throw exceptions.
But now back to work, and more Ruby goodness follows later on :)

Leave a Reply