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  alues.  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

> ----- Original Message ----
> From: EustŠ“uio 'TaQ' Rangel <eustaquiorangel / gmail.com>
> To: ruby-talk ML <ruby-talk / ruby-lang.org>
> Sent: Tuesday, September 30, 2008 6:14:35 PM
> Subject: Re: Mode method for Array
>
>> I'd like to write a get_mode method for the Array class.  The  
>> method would return an array of the most frequently occurring  
>> element or elements.
>> So [3, 1, 1, 55, 55].get_mode would return [1, 55].
>> I have a way to do this but I don't know if it's the best way.  I  
>> was wondering if anyone had any suggestions?
>
> What is your way? Maybe we can have some idea of what parameters you  re using
> to the the most frequently elements. Using something like
>
> irb(main):001:0> [3,1,1,55,55].inject(Hash.new(0)){|memo,item|  
> memo[item] += 1;
> memo}.sort_by {|e| e[1]}.reverse
> => [[55, 2], [1, 2], [3, 1]]
>
> can return you some elements ordered by frequency.

Rob Biedenharn		http://agileconsultingllc.com
Rob / AgileConsultingLLC.com