Robert Klemme
1/4/2006 1:15:00 PM
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