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

Discussion in 'Ruby' started by x1, Oct 12, 2006.

  1. x1

    x1 Guest

    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.
     
    x1, Oct 12, 2006
    #1
    1. Advertising

  2. x1

    Phrogz Guest

    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]]
     
    Phrogz, Oct 12, 2006
    #2
    1. Advertising

  3. Re: Counting Frequency of Values in an Array (And Sorting byFrequency?)

    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.
     
    Logan Capaldo, Oct 12, 2006
    #3
  4. 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
     
    Nobuyoshi Nakada, Oct 12, 2006
    #4
  5. x1

    x1 Guest

    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 <> 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
    >
    >
     
    x1, Oct 12, 2006
    #5
  6. x1

    x1 Guest

    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 += 1
    else
    items = 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 <> 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 <> 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
    > >
    > >

    >
     
    x1, Oct 12, 2006
    #6
  7. items =3D Hash.new(0)
    ["a","a","a","b","c","c"].each do |i|
    items +=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 +=3D 1
    > else
    > items =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?
     
    Daniel Sheppard, Oct 12, 2006
    #7
  8. x1

    Park Heesob Guest

    Hi,
    >From: x1 <>
    >Reply-To:
    >To: (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
     
    Park Heesob, Oct 12, 2006
    #8
  9. x1

    x1 Guest

    Ah ok.. I'm with ya. Meet "sort_by", my new friend. Thanks again :-D

    On 10/12/06, Daniel Sheppard <> wrote:
    > items = Hash.new(0)
    > ["a","a","a","b","c","c"].each do |i|
    > items += 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 += 1
    > > else
    > > items = 1
    > > end
    > > end
    > >
    > > items.sort {|a,b| a[1]<=>b[1]}.reverse.each do |a, b|
    > > puts a + ":" + b.to_s
    > > end
    > >
    > >
    > > horrific eh?

    >
    >
    >
     
    x1, Oct 12, 2006
    #9
  10. On 10/11/06, 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 ?
    >


    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/
     
    Rick DeNatale, Oct 12, 2006
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    8
    Views:
    849
  2. Jen
    Replies:
    3
    Views:
    226
    Robert Klemme
    Mar 23, 2011
  3. PerlFAQ Server
    Replies:
    0
    Views:
    211
    PerlFAQ Server
    Feb 1, 2011
  4. PerlFAQ Server
    Replies:
    0
    Views:
    201
    PerlFAQ Server
    Mar 26, 2011
  5. edwardfredriks

    counting up instead of counting down

    edwardfredriks, Sep 6, 2005, in forum: Javascript
    Replies:
    6
    Views:
    207
    Dr John Stockton
    Sep 7, 2005
Loading...

Share This Page