user3472065
user3472065

Reputation: 1389

In RUBY Sort a table by a field

I need to sort (ascending order) a table by a field.

This is my table:

    vTable=Text::Table.new
    vTable.head= ["Value", "Rest", "NumberRun"]

I store my data in the table inside a loop

    lp= [value, rest, num]
    vTable.rows << lp

After completing my table, it looks like:

 33183   | 109        | 5.10.0.200
 34870   | 114        | 5.4.1.100
 28437   | 93         | 5.6.0.050 
 31967   | 105        | 5.6.2.500 
 29942   | 98         | 5.7.2.900 

I would like to sort, ascending order, this table by "NumberRun" considering that 5.10.0.200 is bigger than 5.7.2.900.

My idea was to remove "." from "NumberRun", convert it into a number, and then sort. In this way 5.10.x > 5.9.x

Upvotes: 1

Views: 167

Answers (2)

sschmeck
sschmeck

Reputation: 7685

You can sort the rows the following way. It uses the Array#sort_by!() method, which was introduced with Ruby 1.9.2.

vTable.rows.sort_by! { |_,_,num| num.split('.').map(&:to_i) }

It also uses Destructuring for the block parameters of sort_by!().

For Ruby versions older than 1.9.2 you can sort the rows and reassign them.

vTable.rows = vTable.rows.sort_by { |_,_,num| num.split('.').map(&:to_i) }

Upvotes: 1

Raman
Raman

Reputation: 1281

I have created a NumberRun class for you that can do the comparision.

#number_run.rb
class NumberRun
  include Comparable
  attr_accessor :run_number
  def initialize(str)
    @run_number = str
  end

  def <=> str1
    str_split = @run_number.split(".")
    str1_split = str1.run_number.split(".")
    output = 0
    str_split.each_with_index do |num, index|
      if((num.to_i <=> str1_split[index].to_i) != 0 && index != (str_split.count - 1))
        output = (num.to_i <=> str1_split[index].to_i)
        break
      elsif index == (str_split.count - 1)
        output = (num.to_i <=> str1_split[index].to_i)
      end
    end
    output
  end
end

For an example:

a = [
  NumberRun.new('5.10.0.200'),
  NumberRun.new('5.4.1.100'),
  NumberRun.new('5.6.0.050'),
  NumberRun.new('5.6.2.500'),
  NumberRun.new('5.7.2.900')
]

a.sort.map(&:run_number)

Upvotes: 0

Related Questions