On 21.04.2007 20:16, Larme wrote:
> Dear all, I'm a newbie to ruby and today when I'm writing a simple
> script to process some data, I found something I can't understand.
> 
> The data is stored in several column seperated by tab or space.  I use
> the following code to get the data (assuming the data comes from
> standard input and all numbers are integer)
> 
> data=[]
> counter = 0
> while line = STDIN.gets
>   data[counter] = line.split
>   data[counter].map! {|str| str.to_i}
>   counter += 1
> end
> 
> hence data[i] is an array hold all the numbers in the ith line, data[i]
> [j] is the number on ith line and jth column. Then what I want the
> script to do is sorting lines according to a specified column.  I
> thought the following code should work:
> 
> result = data.sort {|x, y| x[col] <=> y[col] }
> 
> where the col determine which column the script will sort according
> to. However ruby raise a error saying:
> "undefined method `<=>' for nil:NilClass (NoMethodError)
>         from ana.rb:16:in `sort'
>         from ana.rb:16
> "
> 
> I have to write the code as
> 
> result = data.sort {|x, y| x[col].to_i <=> y[col].to_i }
> 
> to let the script run properly. I'm quite confused here. I think the
> elements of array data are converted to integer when the code
> 
>   data[counter].map! {|str| str.to_i}
> 
> finished. However why ruby still requires a explicit conversion when I
> use the data.sort?

You probably have lines with differing number of entries and thus 
sometimes x[col] just returns nil.

You could do something like:

data.sort_by {|x| x[col].to_i}
data.sort_by {|x| x[col] || 0}

If you want to be sure that you extract only integers you could do

l.scan(/\d+/).map {|x| x.to_i}

instead of the split.

Lots of options...

Kind regards

	robert