From: Robert Klemme Date: 2006-01-04T22:17:58+09:00 Subject: Re: Newbie question about nested sort Grehom wrote: > what am I doing wrong? I wanted to sort primarily on count (second > position in array), then sub-sort alphabetically (first position in > array) > > char_freq = [["c", 2],["b", 5],["a", 2]] > sorted_freq = char_freq.sort {|a, b| b[1]<=>a[1] || a[0]<=>b[0] } > sorted_freq.each do |d| > print d[0]*d[1] > end > > produces >> bbbbbccaa > > when I was rather hoping for >> bbbbbaacc > > I tried using brackets and using 'or' instead of '||' even tried the > sort_by method, any help much appreciated I know this works in perl > (add 13 dollar signs, etc and shake well!): > > use strict; > use warnings; > my @char_freq = (["c", 2], ["b", 5], ["a", 2]); > foreach my $d (sort {$$b[1] <=> $$a[1] || $$a[0] cmp $$b[0] } > @char_freq) { > print $$d[0] x $$d[1] > } > > produces >> bbbbbaacc Generally you need to do conditional evaluation based on higher prio results. Using "||" or "or" won't help here (dunno what Perl does here). You want something like char_freq = [["c", 2],["b", 5],["a", 2]] sorted_freq = char_freq.sort do |a, b| c = b[1]<=>a[1] c == 0 ? a[0]<=>b[0] : c end sorted_freq.each do |d| print d[0]*d[1] end You can make your life easier (though less efficient) with a helper: def multi_compare(*results) results.each {|c| return c if c != 0} 0 end char_freq = [["c", 2],["b", 5],["a", 2]] sorted_freq = char_freq.sort {|a,b| multi_compare(b[1]<=>a[1], a[0]<=>b[0])} sorted_freq.map {|a,b| a*b}.join >> char_freq = [["c", 2],["b", 5],["a", 2]] => [["c", 2], ["b", 5], ["a", 2]] >> sorted_freq = char_freq.sort {|a,b| multi_compare(b[1]<=>a[1], a[0]<=>b[0])} => [["b", 5], ["a", 2], ["c", 2]] >> sorted_freq.map {|a,b| a*b}.join => "bbbbbaacc" You can also do something like this which avoids evaluation of all conditions: class Integer # condition chain def cc() self == 0 ? yield : self end end char_freq = [["c", 2],["b", 5],["a", 2]] sorted_freq = char_freq.sort {|a,b| (b[1]<=>a[1]).cc { a[0]<=>b[0] }} sorted_freq.map {|a,b| a*b}.join >> char_freq.sort {|a,b| (b[1]<=>a[1]).cc { a[0]<=>b[0] }}.map {|a,b| a*b}.join => "bbbbbaacc" HTH Kind regards robert