[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Making nil comparable.

Robert Schaaf

6/5/2009 7:56:00 PM

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




5 Answers

Brian Candler

6/5/2009 8:05:00 PM

0

Robert Schaaf 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?

--
Posted via http://www.ruby-....

Rob Biedenharn

6/5/2009 8:15:00 PM

0

On Jun 5, 2009, at 3:56 PM, Robert Schaaf 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?
>
> 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 Biedenharn http://agileconsult...
Rob@AgileConsultingLLC.com



Robert Schaaf

6/5/2009 9:36:00 PM

0

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 Burt'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


On Jun 5, 2009, at 4:05 PM, Brian Candler wrote:

> Robert Schaaf 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?
>
> --
> Posted via http://www.ruby-....
>


Eric Hodel

6/5/2009 10:17:00 PM

0

On Jun 5, 2009, at 12:56, Robert Schaaf 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.

Joel VanderWerf

6/5/2009 10:39:00 PM

0

Robert Schaaf wrote:
> 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"]

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

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407