How can i do 'foreach (reverse sort { $hasref->{$a} <=> $hasref->{$b} } keys %{$hasref})..' in ruby

A

Aleksandar Lazic

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 ;-)

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:
 
R

Robert Klemme

Aleksandar Lazic said:
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 ;-)

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}"
}

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
 
A

Aleksandar Lazic

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, ;-).
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]]

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
 
D

Daniel Sheppard

For the archive:
=20
My working line is know:
=20
clients.sort{|(k1,v1),(k2,v2)| v2 <=3D> v1}.each{|k,v|=20
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)=09
}

Or:

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

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 =3D {}
1_000_000.times {|i| hash =3D rand}
Benchmark.bm(22) {|bm|
bm.report('sort') {hash.sort{|(k1,v1),(k2,v2)| v2 <=3D> =
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)
 
A

Aleksandar Lazic

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top