Forum: Ruby Sorting array with nils

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
0026dd77fd9ecc97b36e5b79cdbcf590?d=identicon&s=25 R. Kumar (sentinel)
on 2009-01-24 11:05
I have been browsing but given answers are not suiting me.

I hava a double dim array like a dataset.
I thus *cannot* use compact since that would knock off rows. Some
answers say a nil cannot be compared to another datatype so the question
of putting such rows at the beginning or end does not arise.

I am trying to check for nils and using a "false/true" or -1/1 etc but
all are giving errors. Could someone help me out with this.

  def sort categ, column, descending=false
    d = get_records_for_category categ
    d = d.sort { |y,x|
      if descending
        if x[column].nil?
          true   # <<<<------------- errors
        elsif y[column].nil?
          false
        else
          x[column] <=> y[column]
        end
      else
        if x[column].nil?
          1     # <<<-------------- gives errors
        elsif y[column].nil?
          -1
        else
          y[column] <=> x[column]
        end
      end
    }
    return d
  end

Since its a double dim array, i cannot say what the datatype will be:
can be string, fixnum, date or true/false.

I figured since "A" <=> "B" reutrns -1,0 or 1, i should also put one of
these in the loop but it throws an error.

thanks.
Cf7cd97cdc8ed7d4ae92965b24f0dfad?d=identicon&s=25 Stefan Rusterholz (apeiros)
on 2009-01-24 11:18
(RK) Sentinel wrote:
>   def sort categ, column, descending=false
>     d = get_records_for_category categ
>     d = d.sort { |y,x|
>       if descending
>         if x[column].nil?
>           true   # <<<<------------- errors --- yes of course, <=> expectes -1,0,1, not 
true/false
>         elsif y[column].nil?
>           false   # <<<<------------- errors too, for the same reason
>         else
>           x[column] <=> y[column]
>         end
>       else
>         if x[column].nil?
>           1     # <<<-------------- gives errors --- no, should not
>         elsif y[column].nil?
>           -1
>         else
>           y[column] <=> x[column]
>         end
>       end
>     }
>     return d
>   end

A solution (untested):
class Uncomparable
  def initialize(always_less=true)
    @compare = always_less ? -1 : 1
  end

  def <=>(other)
    Uncomparable === other ? 0 : @compare
  end
end
...
d.sort_by { |row| row[column] || Uncomparable(!descending) }
...

Depending on what end you want the nils, you have to change !descending
to just descending.

Regards
Stefan
0026dd77fd9ecc97b36e5b79cdbcf590?d=identicon&s=25 R. Kumar (sentinel)
on 2009-01-24 11:26
(RK) Sentinel wrote:
> I have been browsing but given answers are not suiting me.
>>
> I figured since "A" <=> "B" reutrns -1,0 or 1, i should also put one of
> these in the loop but it throws an error.
>
> thanks.

My apologies:

did some further debugging and one Time value format was different from
the others.
It is okay to use -1 and 1 after checking for nil?.

Cheers
This topic is locked and can not be replied to.