[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: Mode method for Array

Glenn

9/30/2008 10:30:00 PM

Hi,=0A=0AI wrote 2 ways. I don't know if either way is good or not. Any f=
eedback is welcome.=0A=0AThe 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 oc=
cur as the values. Then I create a new hash out of that first hash with th=
e frequencies as the keys of the hash and the elements that had that freque=
ncy as the values. Then I pick out the value of the highest key.=0A=0AThe =
second way creates that frequency hash, then iterates over the hash and cre=
ates an array with the elements that have the highest frequency.=0A=0A clas=
s Array =0A def hash_of_frequency=0A h =3D Hash.new(0)=0A each_with=
_index do |e, i|=0A e =3D e.to_f if e !=3D nil=0A h[e] =3D h[e] +=
=3D 1 =0A end=0A h=0A end=0A=0A def get_mode=0A h =3D hash_of_fr=
equency.frequency_in_key=0A h[h.keys.max].sort=0A end=0Aend=0A=0Aclass =
Hash=0A def frequency_in_key=0A h =3D Hash.new { |k, v| k[v] =3D [] }=
=0A each { |k, v| h[v] << k if k !=3D nil }=0A h=0A end=0A=0A def g=
et_mode=0A a =3D []=0A max_value =3D values.max=0A each { |k, v| a=
<< k if v =3D=3D max_value }=0A a=0A end=0Aend=0A=0A=0A[3, 1, 1, 55, 5=
5].hash_of_frequency.get_mode.inspect ## returns [1.0, 55.0]=0A[3, 1, 1, 55=
, 55].get_mode.inspect ## returns[1.0, 55.0]=0A=0A=0A=0A----- Original Mess=
age ----=0AFrom: Eust=E1quio 'TaQ' Rangel <eustaquiorangel@gmail.com>=0ATo:=
ruby-talk ML <ruby-talk@ruby-lang.org>=0ASent: Tuesday, September 30, 2008=
6:14:35 PM=0ASubject: Re: Mode method for Array=0A=0A> 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.=0A> So [3, 1, 1, 55, 55]=
get_mode would return [1, 55].=0A> I have a way to do this but I don't kno=
w if it's the best way. I was wondering if anyone had any suggestions?=0A=
=0AWhat is your way? Maybe we can have some idea of what parameters you are=
using=0Ato the the most frequently elements. Using something like=0A=0Airb=
(main):001:0> [3,1,1,55,55].inject(Hash.new(0)){|memo,item| memo[item] +=3D=
1;=0Amemo}.sort_by {|e| e[1]}.reverse=0A=3D> [[55, 2], [1, 2], [3, 1]]=0A=
=0Acan return you some elements ordered by frequency.
2 Answers

Rob Biedenharn

9/30/2008 11:03:00 PM

0

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://agileconsult...
Rob@AgileConsultingLLC.com


Todd Benson

9/30/2008 11:20:00 PM

0

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