Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Hash Sorting

Reply
Thread Tools

Hash Sorting

 
 
Nathan Viswa
Guest
Posts: n/a
 
      11-29-2007
Can not understand how the block after sort works! Need help. thanks.

h = { "a" => 20, "b" => 30, "c" => 10 }
puts h.sort #=> [["a", 20], ["b", 30], ["c", 10]]
puts h.sort {|a,b| a[0]<=>b[0]} # as above
puts h.sort {|a,b| a[1]<=>b[1]} #=> [["c", 10], ["a", 20], ["b", 30]]

I:\RubyNV>zzz-tut6-hash.rb
a
20
b
30
c
10

a
20
b
30
c
10

c
10
a
20
b
30

I:\RubyNV>
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
Stefano Crocco
Guest
Posts: n/a
 
      11-29-2007
Alle gioved=C3=AC 29 novembre 2007, Nathan Viswa ha scritto:
> Can not understand how the block after sort works! Need help. thanks.
>
> h =3D { "a" =3D> 20, "b" =3D> 30, "c" =3D> 10 }
> puts h.sort #=3D> [["a", 20], ["b", 30], ["c", 10]]
> puts h.sort {|a,b| a[0]<=3D>b[0]} # as above
> puts h.sort {|a,b| a[1]<=3D>b[1]} #=3D> [["c", 10], ["a", 20], ["b", 3=

0]]

What Hash#sort does is:=20
* first: convert the hash into a nested array:
[['a', 20], ['b', 30], ['c', 10]]
* second: sort that array according to the block.

In the first call to sort, you don't pass a block to it, so the sorting wil=
l=20
be performed by calling the <=3D> of the contents of the array (i.e, on the=
=20
key - value arrays). Array#<=3D> compares the contents of the two arrays in=
=20
order, returning +1 or -1 as soon as one of the items is different from the=
=20
other. For example, ['a', 20]<=3D>['c', 10] returns -1 because 'a'=20
precedes 'c'. If two entries had the same first element (here this is=20
impossible since they come from a hash), the second element would be=20
compared, an so on.

Your second call to send gives the same result, because you're explicitly=20
telling sort to compare only the first element of the array. As explained=20
above, even in the blockless case sort never needs to check the second=20
element, so the results are the same.

In the third case, you tell sort to compare the second element of each pair=
=20
(i.e, the value in the original hash). This way, the pair ['c', 10] becomes=
=20
the first, because 10 is the lesser of the three values; ['a', 20] is the=20
second because 20 is the middle value and ['b', 30] is the last because 30 =
is=20
the greater value.

I hope this helps

Stefano

 
Reply With Quote
 
 
 
 
Jesús Gabriel y Galán
Guest
Posts: n/a
 
      11-29-2007
On Nov 29, 2007 11:09 AM, Nathan Viswa <(E-Mail Removed)> wrote:
> Can not understand how the block after sort works! Need help. thanks.
>
> h = { "a" => 20, "b" => 30, "c" => 10 }
> puts h.sort #=> [["a", 20], ["b", 30], ["c", 10]]
> puts h.sort {|a,b| a[0]<=>b[0]} # as above
> puts h.sort {|a,b| a[1]<=>b[1]} #=> [["c", 10], ["a", 20], ["b", 30]]


As can be read in the documentation:

Converts hsh to a nested array of [ key, value ] arrays and sorts it,
using Array#sort.

This means that sort will convert the array to this (in some order):

[["a", 20], ["b", 30], ["c", 10]]

and then call array sort on it. Checking the documentation on Array#sort:


Returns a new array created by sorting self. Comparisons for the sort
will be done using the <=> operator or using an optional code block.
The block implements a comparison between a and b, returning -1, 0, or
+1. See also Enumerable#sort_by.

a = [ "d", "a", "e", "c", "b" ]
a.sort #=> ["a", "b", "c", "d", "e"]
a.sort {|x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]


What this means is that in the block form, whenever the sort algorithm
needs to compare two elements of the array, it will yield to the block
passing both elements (remember that each element is itself an array
of [key,value] generated by the hash) and expecting a -1, 0 or 1
result, depending on which one you consider to be less than the other
or if they are equal.

In the case of the hash example above:

h.sort {|a,b| a[0]<=>b[0]}

the block will receive, for example:
a = ["a", 20]
b = ["b", 30]

or

a = ["a", 20]
b = ["c", 10]

or whatever pairs the sorting algorithm needs to compare. Then inside
the block you need to provide the comparison of the two elements. The
first example is doing a comparison of the keys, because the first
element of the pair is the hash key, so:

a[0] <=> b[0]

calls the spaceship operator on the keys of the hash. While the second
one a[1] <=> b[1] compares the values of the hash.

Hope this makes any sense.

Jesus.

 
Reply With Quote
 
Nathan Viswa
Guest
Posts: n/a
 
      11-29-2007
Thanks Stefano, Jesus for your time and explanation. Makes sense now.
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Nico Ritsche
Guest
Posts: n/a
 
      01-28-2008
Nathan Viswa wrote:
> Thanks Stefano, Jesus for your time and explanation. Makes sense now.



Hi,

I'm also trying to sort a hash, but don't succeed for some reason.

My hash is build like this:

hash['key1'] = array_of_database_records_type_1
hash['key2'] = array_of_database_records_type_2
hash['key3'] = array_of_database_records_type_3
hash['key4'] = array_of_database_records_type_4

..
..

and so on. The hash's data values are arrays of rails active record
objects,
receifed from a find(:all) call, although their type shouldn't be of
importance when sorting by key, as I do:

sorted_hash_array = hash.sort

The array I receive is not sorted by keys at all, in fact its the same
array I get when I call hash.to_a without any sorting.

Sitting on this 'simple' problem for a few hours now, having no idea
what's the problem.

Any ideas?

Nico


--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
James Tucker
Guest
Posts: n/a
 
      01-28-2008

On 28 Jan 2008, at 17:45, Nico Ritsche wrote:
>
> Any ideas?


hash.to_a.sort


 
Reply With Quote
 
Nico Ritsche
Guest
Posts: n/a
 
      01-28-2008
James Tucker wrote:
> On 28 Jan 2008, at 17:45, Nico Ritsche wrote:
>>
>> Any ideas?

>
> hash.to_a.sort


Tried that, the result is the same, no sorting is happening at all.
Same as if I just do hash.to_a.
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Ilan Berci
Guest
Posts: n/a
 
      01-28-2008
Nico Ritsche wrote:
> James Tucker wrote:
>> On 28 Jan 2008, at 17:45, Nico Ritsche wrote:
>>>
>>> Any ideas?

>>
>> hash.to_a.sort

>
> Tried that, the result is the same, no sorting is happening at all.
> Same as if I just do hash.to_a.


James is correct, the array will be sorted but the hash will remain
"unsorted". Hashes are random access unsorted collections.. you can't
"sort" a hash..

you can however as James suggested, move the elements to a hash and then
sort the result any way you want..

irb(main):001:0> h = {1=>2,3=>4,5=>6}
=> {5=>6, 1=>2, 3=>4}
irb(main):002:0> h.to_a.sort
=> [[1, 2], [3, 4], [5, 6]]
irb(main):003:0> h.to_a.sort_by {|a,b| b}
=> [[1, 2], [3, 4], [5, 6]]
irb(main):004:0>
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Ilan Berci
Guest
Posts: n/a
 
      01-28-2008
Ilan Berci wrote:

>
> you can however as James suggested, move the elements to a hash and then
> sort the result any way you want..
>

errrr.. I mean move the elements to an array.. sorry for the confusion

ilan

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Nico Ritsche
Guest
Posts: n/a
 
      01-28-2008
Ilan Berci wrote:
> Ilan Berci wrote:
>
>>
>> you can however as James suggested, move the elements to a hash and then
>> sort the result any way you want..
>>

> errrr.. I mean move the elements to an array.. sorry for the confusion
>
> ilan




Well, yea, but that is what I did, with no success. The hash.sort
function
simply calls .to_a and then sort on the generated array, so it does
exactly what you and James suggested. Unfortunately the array is not
sorted when I iterate over it using

array.each do
...
end

Is it because iterating like this doesn't preserve the order of array
elements? I assumed .each do iterates in element order. I will test
this...
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
hash of hash of hash of hash in c++ rp C++ 1 11-10-2011 04:45 PM
Sorting list vs sorting vector boltar2003@boltar.world C++ 2 07-06-2010 09:40 AM
Hash#select returns an array but Hash#reject returns a hash... Srijayanth Sridhar Ruby 19 07-02-2008 12:49 PM
Sorting a hash containing a hash of hashes IanW Perl Misc 3 12-14-2005 03:02 PM
[Nuby] Sorting a Hash and keepint it as a Hash? Williams, Chris Ruby 3 12-13-2004 09:04 PM



Advertisments