How to simplify the process of classifying a hash based on values

1

Oops, I'm new to the site, as well as Ruby.

My question is: Is there a more efficient way to sort a hash according to values?

I made the code below, but I'm sure it's not the most efficient way.

agents = {"pedro" => 7, "lucas" => 12, "gabriel" => 15, "tadeu" => 4, "denis" => 22, "fabio" => 0}

agents_array = agents.sort_by { |k, v| v }.reverse

agents_array.map { |element| element.rotate! 1 }

agents_ordered = Hash.new

agents_array.each do |element|
    agents_ordered[element[1]] = agents[element[1]]
end

puts agents_ordered.inspect
  

Input: agents = {"pedro" = > 7, "lucas" = > 12, "gabriel" = > 15, "tadeu"   = > 4, & quot; denis & quot; = > 22, "fabio" = > 0}

     

Expected Outup: agents_ordered = {"denis" = > 22, "gabriel" = > 15,   "lucas" = > 12, "pedro" = > 7, "tadeu" = > 4, "fabio" = >

What would be the most efficient way to qualify?

    
asked by anonymous 07.02.2018 / 20:08

2 answers

1

This problem can be solved by simply using only the available libraries in ruby.

agents = {"pedro" => 7, "lucas" => 12, "gabriel" => 15, "tadeu" => 4, "denis" => 22, "fabio" => 0}.sort_by{|key, value| value }.reverse.to_h
=> {"denis"=>22, "gabriel"=>15, "lucas"=>12, "pedro"=>7, "tadeu"=>4, "fabio"=>0}

It's worth noting that you only experience performance issues when data volume is quite high. Here's a simple performance comparison:

require 'benchmark'
require 'securerandom'

data = {}

1000000.times do |d|
  data[SecureRandom.hex] = rand(1..1000000)
end

Benchmark.bm do |x|
  #implementação mais rápida
  x.report do
    data.sort_by {|_key, value| value}.reverse.to_h
  end

  # um outra alternativa
  x.report do
    data.sort {|l, r| r.first <=> l.first }.to_h
  end

  # sua implementação
  x.report do
    agents_array = data.sort_by { |k, v| v }.reverse

    agents_array.map { |element| element.rotate! 1 }

    agents_ordered = Hash.new

    agents_array.each do |element|
      agents_ordered[element[1]] = data[element[1]]
    end
  end
end

   user     system      total        real
3.510000   0.010000   3.520000 (  3.539540)
7.150000   0.010000   7.160000 (  7.167365)
4.450000   0.010000   4.460000 (  4.457346)
    
07.02.2018 / 20:41
1

You can simplify your code using only native methods:

agents = {"pedro" => 7, "lucas" => 12, "gabriel" => 15, "tadeu" => 4, "denis" => 22, "fabio" => 0}
# => {"pedro"=>7, "lucas"=>12, "gabriel"=>15, "tadeu"=>4, "denis"=>22, "fabio"=>0}

agents_ordered = agents.sort_by(&:last).reverse.to_h
# => {"denis"=>22, "gabriel"=>15, "lucas"=>12, "pedro"=>7, "tadeu"=>4, "fabio"=>0}
    
07.02.2018 / 20:50