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

**URL:** <https://www.ruby-forum.com/t/how-can-i-do-foreach-reverse-sort-hasref-a-has/74055>\
**Category:** Ruby\
**Created:** [October 29, 2006, 3:55pm UTC](https://www.ruby-forum.com/t/how-can-i-do-foreach-reverse-sort-hasref-a-has/74055 "2006-10-29T15:55:05Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Aleksandar\_L](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/8edcca/32.png) [@Aleksandar\_L](https://www.ruby-forum.com/u/Aleksandar_L)\
**Post date:** [October 29, 2006, 3:55pm UTC](https://www.ruby-forum.com/t/how-can-i-do-foreach-reverse-sort-hasref-a-has/74055/1 "2006-10-29T15:55:05Z")

</div>

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](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

---

<div class="post-metadata">

**Author:** ![Aleksandar\_L](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/8edcca/32.png) [@Aleksandar\_L](https://www.ruby-forum.com/u/Aleksandar_L)\
**Post date:** [October 29, 2006, 4:11pm UTC](https://www.ruby-forum.com/t/how-can-i-do-foreach-reverse-sort-hasref-a-has/74055/2 "2006-10-29T16:11:07Z")

</div>

Aleksandar L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

```

---

<div class="post-metadata">

**Author:** ![Aleksandar\_L](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/8edcca/32.png) [@Aleksandar\_L](https://www.ruby-forum.com/u/Aleksandar_L)\
**Post date:** [October 29, 2006, 4:21pm UTC](https://www.ruby-forum.com/t/how-can-i-do-foreach-reverse-sort-hasref-a-has/74055/3 "2006-10-29T16:21:08Z")

</div>

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

> Aleksandar L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![Aleksandar\_L](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/8edcca/32.png) [@Aleksandar\_L](https://www.ruby-forum.com/u/Aleksandar_L)\
**Post date:** [November 7, 2006, 10:44am UTC](https://www.ruby-forum.com/t/how-can-i-do-foreach-reverse-sort-hasref-a-has/74055/4 "2006-11-07T10:44:01Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Aleksandar\_L](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/8edcca/32.png) [@Aleksandar\_L](https://www.ruby-forum.com/u/Aleksandar_L)\
**Post date:** [November 7, 2006, 10:46am UTC](https://www.ruby-forum.com/t/how-can-i-do-foreach-reverse-sort-hasref-a-has/74055/5 "2006-11-07T10:46:13Z")

</div>

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
