From: Todd Benson Date: 2008-10-01T08:19:46+09:00 Subject: Re: Mode method for Array On Tue, Sep 30, 2008 at 6:02 PM, Rob Biedenharn wrote: > On Sep 30, 2008, at 6:30 PM, Glenn wrote: >> >> Hi, >> >> I wrote 2 ways. I don't know if either way is good or not. Any feedback >> is welcome. >> >> The first way makes a hash of the array, with the unique values in the >> array as the keys, and the number of times the keys occur as the values. >> Then I create a new hash out of that first hash with the frequencies as the >> keys of the hash and the elements that had that frequency as the values. >> Then I pick out the value of the highest key. >> >> The second way creates that frequency hash, then iterates over the hash >> and creates an array with the elements that have the highest frequency. >> >> class Array >> def hash_of_frequency >> h = Hash.new(0) >> each_with_index do |e, i| >> e = e.to_f if e != nil >> h[e] = h[e] += 1 >> end >> h >> end > > You never use i, so just use each (and loose the second block parameter) > > h[e] = h[e] += 1 ??? > Did you mean just: h[e] += 1 > >> def get_mode >> h = hash_of_frequency.frequency_in_key >> h[h.keys.max].sort >> end >> end >> >> class Hash >> def frequency_in_key >> h = Hash.new { |k, v| k[v] = [] } >> each { |k, v| h[v] << k if k != nil } >> h >> end >> >> def get_mode >> a = [] >> max_value = values.max >> each { |k, v| a << k if v == max_value } >> a >> end >> end >> >> >> [3, 1, 1, 55, 55].hash_of_frequency.get_mode.inspect ## returns [1.0, >> 55.0] >> [3, 1, 1, 55, 55].get_mode.inspect ## returns[1.0, 55.0] > > If you don't bother with the .to_f on the elements, you could define this > over ANY Enumerable with a variation on what TaQ posted; something like: > > module Enumerable > def mode > alist = inject(Hash.new(0)) {|h,e| h[e]+=1;h}.sort_by {|(e,c)| -c} > alist.select {|(e,c)| c == alist[0][1]}.map{|(e,c)| e} > end > end > > irb> [3,1,1,55,55].mode > => [55, 1] > irb> ['dog','dog','cat','bird',5,5,42].mode > => [5, "dog"] > > -Rob I was thinking similarly... module Enumerable def mode h, max = inject(Hash.new(0)) {|h, i| h[i] += 1; h}, h.values.max h.select {|k, v| v == max}.transpose.first end end p [3, 1, 55, 1, 55].mode => [55, 1] Sort afterward if you want. Todd