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 =20
> feedback is welcome.
>
> The first way makes a hash of the array, with the unique values in =20
> the array as the keys, and the number of times the keys occur as the =20=

> values.  Then I create a new hash out of that first hash with the =20
> frequencies as the keys of the hash and the elements that had that =20
> frequency as the values.  Then I pick out the value of the highest =20
> key.
>
> The second way creates that frequency hash, then iterates over the =20
> hash and creates an array with the elements that have the highest =20
> frequency.
>
> class Array
>  def hash_of_frequency
>    h =3D Hash.new(0)
>    each_with_index do |e, i|
>      e =3D e.to_f if e !=3D nil
>      h[e] =3D h[e] +=3D 1
>    end
>    h
>  end

You never use i, so just use each (and loose the second block parameter)

h[e] =3D h[e] +=3D 1 ???
Did you mean just:  h[e] +=3D 1

>  def get_mode
>    h =3D hash_of_frequency.frequency_in_key
>    h[h.keys.max].sort
>  end
> end
>
> class Hash
>  def frequency_in_key
>    h =3D Hash.new { |k, v| k[v] =3D [] }
>    each { |k, v| h[v] << k if k !=3D nil }
>    h
>  end
>
>  def get_mode
>    a =3D []
>    max_value =3D values.max
>    each { |k, v| a << k if v =3D=3D max_value }
>    a
>  end
> end
>
>
> [3, 1, 1, 55, 55].hash_of_frequency.get_mode.inspect ## returns =20
> [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 =20
this over ANY Enumerable with a variation on what TaQ posted; =20
something like:

module Enumerable
def mode
alist =3D inject(Hash.new(0)) {|h,e| h[e]+=3D1;h}.sort_by {|(e,c)| =
-c}
alist.select {|(e,c)| c =3D=3D alist[0][1]}.map{|(e,c)| e}
end
end

irb> [3,1,1,55,55].mode
=3D> [55, 1]
irb> ['dog','dog','cat','bird',5,5,42].mode
=3D> [5, "dog"]

-Rob

> ----- Original Message ----
> From: Eust=E1quio '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 =20
>> method would return an array of the most frequently occurring =20
>> 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 =20
>> was wondering if anyone had any suggestions?
>
> What is your way? Maybe we can have some idea of what parameters you =20=

> are 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| =20
> memo[item] +=3D 1;
> memo}.sort_by {|e| e[1]}.reverse
> =3D> [[55, 2], [1, 2], [3, 1]]
>
> can return you some elements ordered by frequency.

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