# Making nil comparable

**URL:** <https://www.ruby-forum.com/t/making-nil-comparable/169610>\
**Category:** Ruby\
**Created:** [June 5, 2009, 9:57pm UTC](https://www.ruby-forum.com/t/making-nil-comparable/169610 "2009-06-05T21:57:10Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![rjsquire](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/74df32/32.png) [@rjsquire](https://www.ruby-forum.com/u/rjsquire)\
**Post date:** [June 5, 2009, 9:57pm UTC](https://www.ruby-forum.com/t/making-nil-comparable/169610/1 "2009-06-05T21:57:10Z")

</div>

I have a array of foo objects, each of which contains an array bar  
values. I’d like to sort the foos, ordered by the bars. The problem  
is that the bars are of unequal length.

The most apt example is the numbering in an outline: 1, 1.1, 1.2,  
1.2.1, 1.3 …etc.

In practical terms, comparing 1.1 to 1.2.1 would be [1, 1, nil] \<=\>  
[1, 2, 1]. Array#sort\_by barfs on the nil. Is there some nice way to  
let nil always sort low?

Also having problems with a Regexp, but I can’t find the appropriate  
forum to cry in.

Cheers,

Bob Schaaf

---

<div class="post-metadata">

**Author:** ![rjsquire](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/74df32/32.png) [@rjsquire](https://www.ruby-forum.com/u/rjsquire)\
**Post date:** [June 5, 2009, 10:05pm UTC](https://www.ruby-forum.com/t/making-nil-comparable/169610/2 "2009-06-05T22:05:03Z")

</div>

Robert S. wrote:

> I have a array of foo objects, each of which contains an array bar  
> values. I’d like to sort the foos, ordered by the bars. The problem  
> is that the bars are of unequal length.
> 
> The most apt example is the numbering in an outline: 1, 1.1, 1.2,  
> 1.2.1, 1.3 …etc.
> 
> In practical terms, comparing 1.1 to 1.2.1 would be [1, 1, nil] \<=\>  
> [1, 2, 1]. Array#sort\_by barfs on the nil. Is there some nice way to  
> let nil always sort low?

irb(main):002:0\> [1,1] \<=\> [1,2,1]  
=\> -1

So would

```
sort_by { |x| x.bars.compact }

```

be sufficient?

---

<div class="post-metadata">

**Author:** ![rjsquire](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/74df32/32.png) [@rjsquire](https://www.ruby-forum.com/u/rjsquire)\
**Post date:** [June 5, 2009, 10:15pm UTC](https://www.ruby-forum.com/t/making-nil-comparable/169610/3 "2009-06-05T22:15:21Z")

</div>

On Jun 5, 2009, at 3:56 PM, Robert S. wrote:

> Also having problems with a Regexp, but I can’t find the appropriate  
> forum to cry in.
> 
> Cheers,
> 
> Bob Schaaf

Why make the arrays equal length with nils?

%w[1.3 1.1 1.2.1 1.2 1].sort\_by{|outline| outline.split(‘.’).map{|n|  
n.to\_i} }  
=\> [“1”, “1.1”, “1.2”, “1.2.1”, “1.3”]

We can handle Regexp questions here, too… but you have to toss in a  
bit of ruby to keep it fair. 😉

-Rob

Rob B. [http://agileconsultingllc.com](http://agileconsultingllc.com)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![rjsquire](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/74df32/32.png) [@rjsquire](https://www.ruby-forum.com/u/rjsquire)\
**Post date:** [June 5, 2009, 11:37pm UTC](https://www.ruby-forum.com/t/making-nil-comparable/169610/4 "2009-06-05T23:37:07Z")

</div>

Thanks Brian and Rob,

Yes, of course. Compact will work because the nils are always  
trailing. Thanks greatly.

I should have RTFB.

Now I know this is only peripherally topical, but can anyone come up  
with the regexp that achieves this:

string =~ pattern  
[$1, $2, $3]

where string is a Roman numeral, optionall followed by “(?)” or  
alpha, which, if present can be followed by an Arabic number,

produces

I -\> [“I”, nil, nil]  
I(?) -\> [“I”, “(?)”, nil]  
Ia -\> [“I”, “a”, nil]  
Ib -\> [“I”, “b”, nil]  
IIa1 -\> [“II”, “a”, “1”]  
IIa2 -\> [“II”, “a”, “2”]

As for the trailing nils, I didn’t want to deal with empty strings,  
but since now I’m compacting, I can use reject! instead.

I’ve got Dave B.'s RomanNumerals module, and it was easy to make his  
regexp capturing (and it will be stored as Arabic.)

/^(M\*(?:D?C{0,3}|C[DM])(?:L?X{0,3}|X[LC])(?:V?I{0,3}|I[VX]))$/i

Now that the Ruby stuff is out of the way, who wants to put me out of  
my misery? It’s not like I’m asking you to paint my house!

With interim gratitude,

Bob Schaaf

---

<div class="post-metadata">

**Author:** ![rjsquire](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/74df32/32.png) [@rjsquire](https://www.ruby-forum.com/u/rjsquire)\
**Post date:** [June 6, 2009, 12:40am UTC](https://www.ruby-forum.com/t/making-nil-comparable/169610/5 "2009-06-06T00:40:02Z")

</div>

Robert S. wrote:

> I -\> [“I”, nil, nil]  
> I(?) -\> [“I”, “(?)”, nil]  
> Ia -\> [“I”, “a”, nil]  
> Ib -\> [“I”, “b”, nil]  
> IIa1 -\> [“II”, “a”, “1”]  
> IIa2 -\> [“II”, “a”, “2”]

Do you need the regex to validate the Roman numeral itself? If not, the  
following passes your tests (assuming that you don’t mind compacting out  
the nils). You can do validation subsequently.

rx = /\A([IVXLCDM]+)(?:((?))|([a-z])(\d+)?)?\z/

strs = [  
[“I”, [“I”, nil, nil]],  
[“I(?)”, [“I”, “(?)”, nil]],  
[“Ia”, [“I”, “a”, nil]],  
[“Ib”, [“I”, “b”, nil]],  
[“IIa1”, [“II”, “a”, “1”]],  
[“IIa2”, [“II”, “a”, “2”]]  
]

strs.each do |str, expected|  
if rx.match str  
match = $~.captures  
if match.compact == expected.compact  
puts “#{str.inspect} ok”  
else  
puts “#{str.inspect} fails: match=#{match.inspect}”  
end  
else  
puts “#{str.inspect} fails: not matched”  
end  
end

---

<div class="post-metadata">

**Author:** ![rjsquire](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/74df32/32.png) [@rjsquire](https://www.ruby-forum.com/u/rjsquire)\
**Post date:** [June 6, 2009, 12:19am UTC](https://www.ruby-forum.com/t/making-nil-comparable/169610/6 "2009-06-06T00:19:26Z")

</div>

On Jun 5, 2009, at 12:56, Robert S. wrote:

> I have a array of foo objects, each of which contains an array bar  
> values. I’d like to sort the foos, ordered by the bars. The  
> problem is that the bars are of unequal length.
> 
> The most apt example is the numbering in an outline: 1, 1.1, 1.2,  
> 1.2.1, 1.3 …etc.
> 
> In practical terms, comparing 1.1 to 1.2.1 would be [1, 1, nil] \<=\>  
> [1, 2, 1]. Array#sort\_by barfs on the nil. Is there some nice way  
> to let nil always sort low?

Don’t add nil:

irb(main):003:0\> [[1, 1], [1], [1, 1, 2], [2], [1, 2, 1], [1, 3]].sort  
=\> [[1], [1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2]]

If you have nil, use #compact on each Array you’re sorting first.
