ForryB
ForryB

Reputation: 21

How to sort by value in hash?

So I made a random number generator which is supposed to count the frequency of the numbers and display them in sorted order. I'm trying to use .sort but I can't figure out where to put it to sort the values of the hash in order. What I have so far:

MIN_VALUE = 1
count = 0


puts "Enter a number of random integers to generate"
resp = gets.to_i
p "number of integers generated is #{resp}"


puts "Now enter the maximum value the integers can be"
max_value = gets.to_i
p "max value is set to #{max_value}"


size = Array.new(resp)


while (count < resp)

        int_value = (rand(MIN_VALUE..max_value))
        size.push(int_value)
        count = count + 1

end


puts size



freq = Hash.new(0)
size.each { |x| freq[x] += 1 }
freq.map{ |key, value| "#{key}x#{value}" }.join(',')



freq.each do |key,value|
        puts "Frequency of #{key} is: #{value}"

end

Any help is greatly appreciated!

Upvotes: 2

Views: 142

Answers (2)

iGian
iGian

Reputation: 11193

More or less the same soup, generating random numbers in an Integer#times loop:

upper_number = 10
sample_size = 100

freq = Hash.new(0) # initializing the hash with a default value of zero, for counting
sample_size.times { freq[rand((1..upper_number))] += 1 } # here the loop generating and counting
freq #=> {5=>13, 7=>10, 1=>11, 2=>13, 8=>13, 9=>6, 3=>6, 6=>9, 10=>11, 4=>8}

Then you can sort by frequencies (reverse order: -v) and by sample value (k), [-v, k]:

freq.sort_by{ |k, v| [-v, k] }.to_h #=> {2=>13, 5=>13, 8=>13, 1=>11, 10=>11, 7=>10, 6=>9, 4=>8, 3=>6, 9=>6} # for this run
freq.sum { |_, v| v} #=> 100 # of course

Upvotes: 1

Cary Swoveland
Cary Swoveland

Reputation: 110685

Suppose

arr = [4, 1, 3, 4, 2, 5, 1, 3, 4, 3, 4] 

You can use the form of Hash::new that takes an argument, called its default value (which often, as here, is zero), to obtain the frequency of the elements of arr:

freq = arr.each_with_object(Hash.new(0)) { |n,h| h[n] += 1 }
  #=> {4=>4, 1=>2, 3=>3, 2=>1, 5=>1}

We see that

freq[1]
  #=> 2       
freq[99]
  #=> 0

The second result follows because freq was defined to have a default value of 0. All that means is that if freq does not have a key k, freq[k] returns zero (and that does not alter freq).

Here are solutions to two possible interpretations of your question. Both use the method Enumerable#sort_by.

Sort the unique values of arr by decreasing frequency

freq.sort_by { |_,v| -v }.map(&:first)
  #=> [4, 3, 1, 2, 5] 

Sort the values of arr by decreasing frequency

arr.sort_by { |n| -freq[n] }
  #=> [4, 4, 4, 4, 3, 3, 3, 1, 1, 2, 5] 

Replace -v and -freq[n] with v and freq[n] to sort by increasing frequency.

I've used the local variable _ to represent the keys in the first interpretation to signify that it is not used in the block calculation. This is common practice.

Upvotes: 0

Related Questions