Ordenar una tabla hash de objetos (por los atributos de los objetos) en Ruby

Say I have a class called Person, and it contains things such as last name, first name, address, etc.

I also have a hash table of Person objects that needs to be sorted by last and first name. I understand that a sort_by will not change the hash permanently, which is fine, I only need to print in that order. Currently, I am trying to sort/print in place using:

@hash.sort_by {|a,b| a <=> b}.each { |person| puts person.last}

I have overloaded the <=> operator to sort by last/first, but nothing appears to actually sort. The puts there simply outputs in the hash's original order. I have spent a good 4 days trying to figure this out (it is a school assignment, and my first Ruby program). Any ideas? I am sure this is easy, but I am having the hardest time bringing my brain out of the C++ way of thinking.

preguntado el 01 de febrero de 12 a las 22:02

3 Respuestas

Pareces estar confuso sort y la sort_by

sort yields two objects from the collection to the block and expects you to return a <=> like value: -1,0 or 1 depending on whether the arguments are equal, ascending or descending, for example

%w(one two three four five).sort {|a,b| a.length <=> b.length}

Sorts the strings by length. This is the form to use if you want to use your <=> operator

sort_by yields one object from the collection at a time and expects you to return what you want to sort by - you shouldn't be doing any comparison here. Ruby then uses <=> on these objecfs to sort your collection. The previous example can e rewritten as

%w(one two three four five).sort_by {|s| s.length}

Esto también se conoce como schwartzian transform

In your case the collection is a hash so things are slightly more complicated: the values that are passed into the block are arrays that contain key/value pairs, so you'll need to extract the person object from that pair. You could also just work on @hash.keys or @hash.values (depending on whether the person objects are keys or values)

Respondido 02 Feb 12, 02:02

Learning things like a Schwartzian transform make me a happy guy. I got it now, and I am about to turn it in. Thank you so much for the help and great post. - bo malone

If you've overidden the <=> operator to sort Person objects appropriately then you can simply do:

@hash.sort_by{ |key, person| person }

because sort_by will yield both the hash key, and the object (in your case a person) to each iteration of the block. So the code above will sort your hash based on Person objects - for which you've already specified an <=> operator.

Respondido 02 Feb 12, 02:02

Cuando #.sort_by with a Hash, the parameters passed to the block are 'key','value', not 'element a' and 'element b'. Try:

@hash.sort_by{|key,value| value.last}.each{|key,value| puts value.last}

Also, see Frederick Cheung's excellent explanation of #sort vs #sort_by.

Respondido 02 Feb 12, 02:02

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.