From: Robert Klemme Date: 2005-07-16T16:40:53+09:00 Subject: Re: Cascading <=> comparisons Garance A Drosehn wrote: > On 7/15/05, Ara.T.Howard wrote: >> On Sat, 16 Jul 2005, Garance A Drosehn wrote: >> >>> That's pretty easy, but what if I want to cascade comparisons >>> in that sort, such that if the data-values are equal, then I want >>> the sort order to be based on some other comparison? ... >> >> [vals[kb], ka] <=> [vals[ka], kb] >> >> note that the array approach scales for any number of things, >> not only two. you can always do >> >> [a,b,c] <=> [x,y,z] >> >> even if a, b, and c are different types. so long as you can >> >> a <=> x >> b <=> y >> c <=> z > > Ooo. Very nice. Thanks! > > The suggestions to look at sort_by (from Enumerable) and > the idea of: (vals[kb] <=> vals[ka]).nonzero? or (ka <=> kb) > were also very useful. Thanks to all. Noone explicitely commented on the use of hash.keys.sort: this is quite inefficient. Instead doing the sort on the hash directly is much more efficient: >> hash = { "a" => 1, "b" => 4, "c" => 3, "d" => 1 } => {"a"=>1, "b"=>4, "c"=>3, "d"=>1} >> hash.sort {|a,b| a.reverse <=> b.reverse} => [["a", 1], ["d", 1], ["c", 3], ["b", 4]] This technique can be applied to sort_by, too: >> hash.sort_by {|a| a.reverse} => [["a", 1], ["d", 1], ["c", 3], ["b", 4]] But this shows a strange anomaly - this seems like a bug in 1.8.2. >> hash.sort_by {|a| a.reverse!} => [[1, "a"], [1, "d"], [3, "c"], [4, "b"]] You can also directly chain printing: >> hash.sort_by {|a| a.reverse}.each {|k,v| printf "%3d %s\n", v, k} 1 a 1 d 3 c 4 b => [["a", 1], ["d", 1], ["c", 3], ["b", 4]] Kind regards robert