Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Counting Frequency of Values in an Array (And Sorting by Frequency?)

Reply
Thread Tools

Counting Frequency of Values in an Array (And Sorting by Frequency?)

 
 
x1
Guest
Posts: n/a
 
      10-12-2006
Is there no method for an array that will tell me the # of occurrences
for an item?

IE: ["a", "a", "a", "b", "c", "c"].count("a") #producing 3 ?

I almost thought that rindex would do the trick when looking at the
class docs but.. the example was just engineered to trick me

I realize I could pass these to a block and count but.. wanted to make
sure it didn't exist. If not, why? Thank you.. ( I did search btw.. no
avail )

Also, what's the best way of printing out each unique item and the
number of times it occurs, sorted by numerically by the number of
times it occurs?

IE: in my example above, i'd like to see (sorted by occurrence
greatest to least)
#desired output:
a: 3
c: 2
b: 1


Or sorted from least to greatest:
#desired output:
b: 1
c: 2
a: 3

I was able to hack it by using a hash doing various things to it.. but
it didn't seem "rubyish".

Thank you for any input.

 
Reply With Quote
 
 
 
 
Phrogz
Guest
Posts: n/a
 
      10-12-2006
x1 wrote:
> I was able to hack it by using a hash doing various things to it.. but
> it didn't seem "rubyish".


What could be more ruby-ish than monkeypatching a built-in class and
using inject in the process?

class Array
def counts
inject( Hash.new(0) ){ |hash,element|
hash[ element ] +=1
hash
}
end
def counts_up
counts.sort_by{ |k,v| v }
end
def counts_down
counts.sort_by{ |k,v| -v }
end
end
a = ["a", "a", "a", "b", "c", "c"]
p a.counts, a.counts_up, a.counts_down
#=> {"a"=>3, "b"=>1, "c"=>2}
#=> [["b", 1], ["c", 2], ["a", 3]]
#=> [["a", 3], ["c", 2], ["b", 1]]

 
Reply With Quote
 
 
 
 
Logan Capaldo
Guest
Posts: n/a
 
      10-12-2006
On Thu, Oct 12, 2006 at 11:52:19AM +0900, x1 wrote:
> Is there no method for an array that will tell me the # of occurrences
> for an item?
>
> IE: ["a", "a", "a", "b", "c", "c"].count("a") #producing 3 ?
>

array.select { |i| i == 'a' }.length
or array.inject(0) { |count, item| count += 1 if item == 'a'; count }

> I almost thought that rindex would do the trick when looking at the
> class docs but.. the example was just engineered to trick me
>
> I realize I could pass these to a block and count but.. wanted to make
> sure it didn't exist. If not, why? Thank you.. ( I did search btw.. no
> avail )
>
> Also, what's the best way of printing out each unique item and the
> number of times it occurs, sorted by numerically by the number of
> times it occurs?
>
> IE: in my example above, i'd like to see (sorted by occurrence
> greatest to least)
> #desired output:
> a: 3
> c: 2
> b: 1
>
>
> Or sorted from least to greatest:
> #desired output:
> b: 1
> c: 2
> a: 3
>
> I was able to hack it by using a hash doing various things to it.. but
> it didn't seem "rubyish".
>

As you say:
puts array.inject(Hash.new(0)) { |hash, item| hash[item] += 1
hash }.sort_by { |k, v| v }.map { |k, v| "#{k}:#{v}" }
> Thank you for any input.


 
Reply With Quote
 
Nobuyoshi Nakada
Guest
Posts: n/a
 
      10-12-2006
Hi,

At Thu, 12 Oct 2006 11:52:19 +0900,
x1 wrote in [ruby-talk:219218]:
> Is there no method for an array that will tell me the # of occurrences
> for an item?
>
> IE: ["a", "a", "a", "b", "c", "c"].count("a") #producing 3 ?


FYI, Enumerable in 1.9 has that method.

--
Nobu Nakada

 
Reply With Quote
 
x1
Guest
Posts: n/a
 
      10-12-2006
Wow Capaldo, that worked! I fear for the next java programmer who has
to make sense of my code when I leave

To reverse sort, I added .reverse.. Here's the final product:
puts ["a", "a", "a", "b", "c", "c"].inject(Hash.new(0)) { |hash, item|
hash[item] += 1
hash }.sort_by { |k, v| v }.reverse.map { |k, v| "#{k}:#{v}" }

Thanks so much.

Nakada, I look forward to using it in 1.9

On 10/11/06, Nobuyoshi Nakada <(E-Mail Removed)> wrote:
> Hi,
>
> At Thu, 12 Oct 2006 11:52:19 +0900,
> x1 wrote in [ruby-talk:219218]:
> > Is there no method for an array that will tell me the # of occurrences
> > for an item?
> >
> > IE: ["a", "a", "a", "b", "c", "c"].count("a") #producing 3 ?

>
> FYI, Enumerable in 1.9 has that method.
>
> --
> Nobu Nakada
>
>


 
Reply With Quote
 
x1
Guest
Posts: n/a
 
      10-12-2006
and.. so you're aware.. my hacky code was something like this:

items = {}
["a", "a", "a", "b", "c", "c"].each do |i|
if items.include? i
items[i] += 1
else
items[i] = 1
end
end

items.sort {|a,b| a[1]<=>b[1]}.reverse.each do |a, b|
puts a + ":" + b.to_s
end


horrific eh?





On 10/11/06, x1 <(E-Mail Removed)> wrote:
> Wow Capaldo, that worked! I fear for the next java programmer who has
> to make sense of my code when I leave
>
> To reverse sort, I added .reverse.. Here's the final product:
> puts ["a", "a", "a", "b", "c", "c"].inject(Hash.new(0)) { |hash, item|
> hash[item] += 1
> hash }.sort_by { |k, v| v }.reverse.map { |k, v| "#{k}:#{v}" }
>
> Thanks so much.
>
> Nakada, I look forward to using it in 1.9
>
> On 10/11/06, Nobuyoshi Nakada <(E-Mail Removed)> wrote:
> > Hi,
> >
> > At Thu, 12 Oct 2006 11:52:19 +0900,
> > x1 wrote in [ruby-talk:219218]:
> > > Is there no method for an array that will tell me the # of occurrences
> > > for an item?
> > >
> > > IE: ["a", "a", "a", "b", "c", "c"].count("a") #producing 3 ?

> >
> > FYI, Enumerable in 1.9 has that method.
> >
> > --
> > Nobu Nakada
> >
> >

>


 
Reply With Quote
 
Daniel Sheppard
Guest
Posts: n/a
 
      10-12-2006
items =3D Hash.new(0)
["a","a","a","b","c","c"].each do |i|
items[i] +=3D 1
end
items.sort_by {|key,value| -value}.each do |key, value|
puts "#{a}:#{b}"
end

Slightly less horrific?

> and.. so you're aware.. my hacky code was something like this:
>=20
> items =3D {}
> ["a", "a", "a", "b", "c", "c"].each do |i|
> if items.include? i
> items[i] +=3D 1
> else
> items[i] =3D 1
> end
> end
>=20
> items.sort {|a,b| a[1]<=3D>b[1]}.reverse.each do |a, b|
> puts a + ":" + b.to_s
> end
>=20
>=20
> horrific eh?



 
Reply With Quote
 
Park Heesob
Guest
Posts: n/a
 
      10-12-2006


Hi,
>From: x1 <(E-Mail Removed)>
>Reply-To: http://www.velocityreviews.com/forums/(E-Mail Removed)
>To: (E-Mail Removed) (ruby-talk ML)
>Subject: Counting Frequency of Values in an Array (And Sorting by
>Frequency?)
>Date: Thu, 12 Oct 2006 11:52:19 +0900
>
>Is there no method for an array that will tell me the # of occurrences
>for an item?
>
>IE: ["a", "a", "a", "b", "c", "c"].count("a") #producing 3 ?
>

You can use ["a", "a", "a", "b", "c", "c"].grep("a").size

>I almost thought that rindex would do the trick when looking at the
>class docs but.. the example was just engineered to trick me
>
>I realize I could pass these to a block and count but.. wanted to make
>sure it didn't exist. If not, why? Thank you.. ( I did search btw.. no
>avail )
>
>Also, what's the best way of printing out each unique item and the
>number of times it occurs, sorted by numerically by the number of
>times it occurs?
>
>IE: in my example above, i'd like to see (sorted by occurrence
>greatest to least)
>#desired output:
>a: 3
>c: 2
>b: 1
>

array.uniq.sort_by{|x|array.grep(x).size}.reverse. each{|x|puts "#{x}:
#{array.grep(x).size}"}

>
>Or sorted from least to greatest:
>#desired output:
>b: 1
>c: 2
>a: 3
>

array.uniq.sort_by{|x|array.grep(x).size}.each{|x| puts "#{x}:
#{array.grep(x).size}"}


Regards,
Park Heesob



 
Reply With Quote
 
x1
Guest
Posts: n/a
 
      10-12-2006
Ah ok.. I'm with ya. Meet "sort_by", my new friend. Thanks again

On 10/12/06, Daniel Sheppard <(E-Mail Removed)> wrote:
> items = Hash.new(0)
> ["a","a","a","b","c","c"].each do |i|
> items[i] += 1
> end
> items.sort_by {|key,value| -value}.each do |key, value|
> puts "#{a}:#{b}"
> end
>
> Slightly less horrific?
>
> > and.. so you're aware.. my hacky code was something like this:
> >
> > items = {}
> > ["a", "a", "a", "b", "c", "c"].each do |i|
> > if items.include? i
> > items[i] += 1
> > else
> > items[i] = 1
> > end
> > end
> >
> > items.sort {|a,b| a[1]<=>b[1]}.reverse.each do |a, b|
> > puts a + ":" + b.to_s
> > end
> >
> >
> > horrific eh?

>
>
>


 
Reply With Quote
 
Rick DeNatale
Guest
Posts: n/a
 
      10-12-2006
On 10/11/06, x1 <(E-Mail Removed)> wrote:
> Is there no method for an array that will tell me the # of occurrences
> for an item?
>
> IE: ["a", "a", "a", "b", "c", "c"].count("a") #producing 3 ?
>


Smalltalk has a collection class called Bag, which is an unordered
collection of objects which keeps track of the number of occurences of
each equal element in the collection, so you can do something like:

bag <- Bag.new
bag.add: 1;add: 2: add: 1; add: 4
bag.occurencesOf: 1 => 2
bag.occurencesOf: 1 => 1
bag.remove: 1
bag.occurrencesOf: 1 => 1

Now Bag is kind of the black sheep of the Smalltalk collection
classes. Most Smalltalkers would either never use it or overuse it.
The only use I could think of was to implement a histogram.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
FAQ 6.15 How can I print out a word-frequency or line-frequency summary? PerlFAQ Server Perl Misc 0 03-26-2011 04:00 AM
Counting values in an array, storing in a hash then making an arrayof hashes? Jen Ruby 3 03-23-2011 12:11 PM
FAQ 6.15 How can I print out a word-frequency or line-frequency summary? PerlFAQ Server Perl Misc 0 02-01-2011 11:00 AM
Counting frequency of words in a text file using STL containers writeanand@gmail.com C++ 8 02-08-2007 08:53 PM
counting up instead of counting down edwardfredriks Javascript 6 09-07-2005 03:30 PM



Advertisments