# Sorting array with nils

**URL:** <https://www.ruby-forum.com/t/sorting-array-with-nils/158527>\
**Category:** Ruby\
**Created:** [January 24, 2009, 11:05am UTC](https://www.ruby-forum.com/t/sorting-array-with-nils/158527 "2009-01-24T11:05:20Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![sentinel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@sentinel](https://www.ruby-forum.com/u/sentinel)\
**Post date:** [January 24, 2009, 11:05am UTC](https://www.ruby-forum.com/t/sorting-array-with-nils/158527/1 "2009-01-24T11:05:20Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![sentinel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@sentinel](https://www.ruby-forum.com/u/sentinel)\
**Post date:** [January 24, 2009, 11:26am UTC](https://www.ruby-forum.com/t/sorting-array-with-nils/158527/2 "2009-01-24T11:26:26Z")

</div>

(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

---

<div class="post-metadata">

**Author:** ![sentinel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/fbc32d/32.png) [@sentinel](https://www.ruby-forum.com/u/sentinel)\
**Post date:** [January 24, 2009, 11:18am UTC](https://www.ruby-forum.com/t/sorting-array-with-nils/158527/3 "2009-01-24T11:18:26Z")

</div>

(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
