0

I want to sort my has by value.I am tried to sort my hash this way and it does not work, I don't know why. This is my code:

test="neki text sa recima neki sa i jos neki aa"
mapa=Hash.new(0)
test.split(" ").each do |rec|
    mapa[rec]+=1
end

mapa.sort_by {|a,b| b}.reverse

mapa.each do |key, value|
    puts "#{key} #{value}" 
end

the output is :

neki 3
text 1
sa 2
recima 1
i 1
jos 1
aa 1

It doesn't do anything to the HASH :/ Can someone explain to me why it does not work?

if you give me a MINUS please explain in the comment what I did to deserve it so I know where to improve. :)

Community
  • 1
  • 1
kemis
  • 4,404
  • 6
  • 27
  • 40
  • Be careful using `sort_by` with simple objects. It adds overhead and can slow the actual sort process. See http://stackoverflow.com/a/2651028/128421 and [the `sort_by` documentation](http://ruby-doc.org/core-2.3.1/Enumerable.html#method-i-sort_by) for a good description and a comparison along with the Wikipedia article on "[Schwartzian Transform](https://en.wikipedia.org/wiki/Schwartzian_transform)". – the Tin Man Jul 18 '16 at 17:34

1 Answers1

3

Enumerable#sort_by never promised to sort the enumerable inplace. It returns the result:

puts mapa.sort_by {|a,b| -b}
#⇒ sorted

or, in more idiomatic manner:

mapa.sort_by(&:last).reverse.each do |k, v|
  puts ...
end

Please note, that when examining the output in irb, the order might not correspond to the real order of elements in a hash, since irb (with print formatters installed) has it’s own ideas on how to output hashes.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • Thank you. So I have to just say mapa = mapa.sort_by {|a,b| b}.reverse . I was didnt know it returns a value, was thinking it changes the HASH. – kemis Jul 18 '16 at 16:29
  • 1
    Well, yes. Basically in ruby all functions that _mutate_ an object, are by convention called having a trailing bang: `sort_by!` would mutate the hash itself (if existed.) – Aleksei Matiushkin Jul 18 '16 at 16:32
  • mudsie, where would you put `mapa.max_by(mapa.size, &:last).to_h #=> {:neki=>3, :sa=>2, :i=>1, :aa=>1, :jos=>1, :text=>1, :recima=>1} ` in the idomatic order? – Cary Swoveland Jul 18 '16 at 17:12
  • @CarySwoveland since idiomatic ruby is to be represented by hash `{way_of_solution => ->() {} }`, it is unordered in ruby :) Well, joking aside, I like `max_by` more than mine `sort_by`. – Aleksei Matiushkin Jul 18 '16 at 17:22