How can i do 'foreach (reverse sort { $hasref->{$a} <=> $has

Hi,

I’am new with ruby and want to migrate some of my perlscripts to ruby
;-).

I have a problem with the ‘reverse sort’ of values of a hashref and hope
that sombody can help me or point me to the right way :wink:

I have found the a nice answer
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/30322

and have try the follwoing commands:

clients.values.sort{|a,b| a[1] <=> b[1]}.each {|k,v|
puts “#{k} => #{v}”
}

clients.values.sort.reverse.each { |k|
puts “#{k}”
}

but it looks to me that sort give me only a array back.

Here my perl code which i want to translate:


foreach (reverse sort { $hasref->{$a} <=> $hasref->{$b} } keys
%{$hasref}){
printf(“% 7i %s\n”,$hasref->{$}, $);
#^^^^^^^Key output ^^value output
}

Thanks for help

Aleks

Aleksandar L. [email protected] wrote:

and have try the follwoing commands:

clients.values.sort{|a,b| a[1] <=> b[1]}.each {|k,v|
puts “#{k} => #{v}”
}

clients.values.sort.reverse.each { |k|
puts “#{k}”
}

Both of these sort values only!

but it looks to me that sort give me only a array back.

Yes, it does - even if you sort the hash. But that’s natural as a Hash
has
no order so returning a Hash would not make sense.

Here my perl code which i want to translate:


foreach (reverse sort { $hasref->{$a} <=> $hasref->{$b} } keys
%{$hasref}){ printf(“% 7i %s\n”,$hasref->{$}, $);
#^^^^^^^Key output ^^value output
}

If you want to reverse sort a Hash by values you can do

sorted = hash.sort {|(k1,v1),(k2,v2)| v2 <=> v1}

You can iterate “sorted” like a hash:

sorted.each {|k,v| print key, " => ", value, “\n”}

In some cases you can use sort_by:

irb(main):001:0> {1=>2,3=>4}.sort_by {|k,v| -v}
=> [[3, 4], [1, 2]]

Kind regards

robert

On Mon 30.10.2006 00:10, Robert K. wrote:

Aleksandar L. [email protected] wrote:

but it looks to me that sort give me only a array back.

Yes, it does - even if you sort the hash. But that’s natural as a Hash
has no order so returning a Hash would not make sense.

Yep, ;-).

You can iterate “sorted” like a hash:

sorted.each {|k,v| print key, " => ", value, “\n”}

In some cases you can use sort_by:

irb(main):001:0> {1=>2,3=>4}.sort_by {|k,v| -v}
=> [[3, 4], [1, 2]]

Many thanks the ‘|(k1,v1),(k2,v2)|’ I haven’t know.

For the archive:

My working line is know:

clients.sort{|(k1,v1),(k2,v2)| v2 <=> v1}.each{|k,v|
printf(“% 7i %s\n”,v, k)
}

Regards

Aleks

For the archive:

My working line is know:

clients.sort{|(k1,v1),(k2,v2)| v2 <=> v1}.each{|k,v|
printf("% 7i %s\n",v, k)
}

For the simple case (such as yours) where the values being sorted are
numeric, I find it neater to just do:

clients.sort_by{|k,v| -v}.each {|k,v|
printf("% 7i %s\n",v, k)
}

Or in the general case:

clients.sort_by{|k,v| v}.reverse.each {|k,v|
printf("% 7i %s\n",v, k)
}

Or:

clients.sort_by{|k,v| v}.reverse_each {|k,v|
printf("% 7i %s\n",v, k)
}

Which is probably clearest in intention (looking at the original code
you post, it’s not immediately apparent the it’s a reverse sort). These
methods have the added benefit of also being the faster code (sort_by is
much faster than sort).

require ‘benchmark’
hash = {}
1_000_000.times {|i| hash[i] = rand}
Benchmark.bm(22) {|bm|
bm.report(‘sort’) {hash.sort{|(k1,v1),(k2,v2)| v2 <=> v1}.each{|k,v|}}
bm.report(‘sort_by @-’) {hash.sort_by{|k,v| -v}.each {|k,v|}}
bm.report(‘sort_by reverse’) {hash.sort_by{|k,v| v}.reverse.each
{|k,v|}}
bm.report(‘sort_by reverse_each’) {hash.sort_by{|k,v| v}.reverse_each
{|k,v|}}
}

                        user     system      total        real

sort 58.094000 0.719000 58.813000 ( 99.922000)
sort_by @- 10.297000 0.046000 10.343000 ( 14.750000)
sort_by reverse 10.922000 0.063000 10.985000 ( 14.687000)
sort_by reverse_each 10.000000 0.016000 10.016000 ( 12.094000)

On Mon 30.10.2006 10:18, Daniel S. wrote:

For the archive:

My working line is know:

clients.sort{|(k1,v1),(k2,v2)| v2 <=> v1}.each{|k,v|
printf("% 7i %s\n",v, k)
}

For the simple case (such as yours) where the values being sorted are
numeric, I find it neater to just do:
[snipp]
Or:

clients.sort_by{|k,v| v}.reverse_each {|k,v|
printf("% 7i %s\n",v, k)
}

Cool ;-)))

Which is probably clearest in intention (looking at the original code
you post, it’s not immediately apparent the it’s a reverse sort). These
methods have the added benefit of also being the faster code (sort_by
is much faster than sort).

You are right but I have hoped that a perl person understand my intetion
and point me to the right ruby solution ;-))

Thanks for your info and time.

Aleks