|
|
Re: Finding ties in sorting?
On Sep 14, 2007, at 8:42 AM, Dan Zwell wrote:
> Axel Etzold wrote:
>> Dear all,
>> I have many arrays like
>> a=[{'a',10,'b',3},{'a',10,'b',4},{'a',5,'b',13},{'a', 13,'b',13},
>> {'a',10,'b',7},{'a',5,'b',3}]
>> which I'd like to sort such that I get the hashes with the highest
>> values of 'a' first. If there are ties, I'd like to sort them (but
>> not
>> the entire array) such
>> that the highest values of 'b' come first.
>> So I can't just sort for 'a'-values first and then for 'b'-values,
>> as this would destroy the first sort order.
>> Is there a built-in way of getting the ties in sorting, such as an
>> Array of the results of the <=> comparisons ?
>> Thank you!
>> Best regards,
>> Axel
>
> Built in? I don't know about that, but it's pretty easy. I'm sure
> your real situation is more complex than the example you gave, but
> I really think this is the easiest way (and you can avoid making
> comparisons twice by caching the value of hash1['a'] <=> hash2
> ['a'], if you wish):
>
> a=[{'a',10,'b',3},{'a',10,'b',4},{'a',5,'b',13},{'a', 13,'b',13},
> {'a',10,'b',7},{'a',5,'b',3}]
> a.sort do |hash1, hash2|
> if hash1['a'] == hash2['a']
> hash1['b'] <=> hash2['b']
> else
> hash1['a'] <=> hash2['a']
> end
> end
>
> The above is essentially a redefinition of <=> on hashes with
> elements "a" and "b". The only thing you need to be sure of is that
> ordering is strict--that you never have x < y < z but z < x. That
> should be no problem if you only try to break ties.
>
> Hope this s,
> Dan
a.sort do |h1,h2|
(h1['a'] <=> h2['a']).nonzero? || h1['b'] <=> h2['b']
end
The Numeric#nonzero? is exactly for this kind of thing. If its
receiver is 0 it returns nil so chaining with || will work. (And you
don't have to compare the 'a' values twice.)
-Rob
Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com
|