Todd Benson
9/30/2008 11:20:00 PM
On Tue, Sep 30, 2008 at 6:02 PM, Rob Biedenharn
<Rob@agileconsultingllc.com> 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