Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Ruby (http://www.velocityreviews.com/forums/f66-ruby.html)
-   -   Count the number of times an element occurs in an array (http://www.velocityreviews.com/forums/t859858-count-the-number-of-times-an-element-occurs-in-an-array.html)

 Jim Burgess 10-05-2009 09:24 AM

Count the number of times an element occurs in an array

Hi,

I need to count the number of times an element occurs in an array.

At the moment I'm doing it like this:

a = ["a", "b", "a", "b", "b"]
b = a.uniq
c = []

0.upto(b.length-1) do |e|
d = 0
0.upto(a.length-1) do |f|
if b[e] == a[f]
d += 1
end
end
c << d
end

print b, c
> ["a", "b"] [2, 3]

This works, but seems really clumsy.
Can anyone give me any tips on what I could improve?
Cheers.
--
Posted via http://www.ruby-forum.com/.

 Ryan Davis 10-05-2009 09:41 AM

Re: Count the number of times an element occurs in an array

On Oct 5, 2009, at 02:24 , Jim Burgess wrote:

> Hi,
>
> I need to count the number of times an element occurs in an array.
>
> At the moment I'm doing it like this:
>
> a = ["a", "b", "a", "b", "b"]
> b = a.uniq
> c = []
>
> 0.upto(b.length-1) do |e|
> d = 0
> 0.upto(a.length-1) do |f|
> if b[e] == a[f]
> d += 1
> end
> end
> c << d
> end
>
> print b, c
>> ["a", "b"] [2, 3]

Some suggestions:

Your indentation is wack. Make sure you're not mixing spaces and tabs.
2 spaces per indent. You're mixing 2 & 3 & possibly tabs at 8.

Your variable names are meaningless. Improve that and you'll have a
lot better time debugging when it is 4am and you're tired.

You're not using (sensible) iterators. I suggest you read that section
in the pickaxe book.

You're not using good data structures or algorithms. You're passing
over the elements of 'a' (see? better names means better readability!)
a.uniq.size times and doing a.size * a.uniq.size string equality
comparisons.

Take a look at this:

# use a hash whose values default to 0 for proper data structure use
# use count as the name, since that's what it is storing.
count = Hash.new 0

# iterate over each string only once
strings.each do |string|
# increment the count for each string
count[string] += 1
end

p count

If you nuke all the comments, the code makes just as much sense (if
not more). That's what we try to achieve in ruby whenever we can.

 Fleck Jean-Julien 10-05-2009 09:43 AM

Re: Count the number of times an element occurs in an array

Hello,

2009/10/5 Jim Burgess <jack.zelig@gmail.com>:
> Hi,
>
> I need to count the number of times an element occurs in an array.

Using Enumerable.count should do the trick:

a =3D ["a", "b", "a", "b", "b"]

a.uniq.each do |elem|
puts "#{elem}\t#{a.count(elem)}"
end

Produces:

a 2
b 3

Cheers,

--=20
JJ Fleck
PCSI1 Lyc=E9e Kl=E9ber

 Jim Burgess 10-05-2009 09:56 AM

Re: Count the number of times an element occurs in an array

>a = ["a", "b", "a", "b", "b"]
>a.uniq.each do |elem|
> puts "#{elem}\t#{a.count(elem)}"
>end

@Fleck Jean-Julien
Thanks for the quick fix. That works perfectly and is miles better than
what I wrote.

@Ryan
Thanks for the suggestions.

> Your indentation is wack. Make sure you're not mixing spaces and tabs.
> 2 spaces per indent. You're mixing 2 & 3 & possibly tabs at 8.

Sorry about that. I'm writing ruby in a virtual Windows on a Linux host.
Formatting got a bit corrupted when copying the code. I'll watch out for
that next time.

> Your variable names are meaningless. Improve that and you'll have a
> lot better time debugging when it is 4am and you're tired.

Sorry. I just did that to make the example easier. In reality they are

> You're not using (sensible) iterators. I suggest you read that section
> in the pickaxe book.

Good tip. I will do that now.

> You're not using good data structures or algorithms.

No kidding :-)

> count = Hash.new 0
>
> # iterate over each string only once
> strings.each do |string|
> # increment the count for each string
> count[string] += 1
> end
>
> p count

Thanks for that. I will try to rewrite my method (for the sake of
learning) in a neater way, using the technique you suggest.

Cheers

--
Posted via http://www.ruby-forum.com/.

 David A. Black 10-05-2009 10:14 AM

Re: Count the number of times an element occurs in an array

Hi --

On Mon, 5 Oct 2009, Jim Burgess wrote:

> Hi,
>
> I need to count the number of times an element occurs in an array.

*** DISCLAIMER ***

This answer is just for fun, and because sometimes seeing useful
techniques in strange contexts helps people learn and remember them.

With that in mind... here's a

>> strings = %w{a b a a c b b b c c c d }

=> ["a", "b", "a", "a", "c", "b", "b", "b", "c", "c", "c", "d"]
>> hash = Hash.new {|h,k| [k, strings.count(k)] }

=> {}
>> hash.values_at(*strings.uniq)

=> [["a", 3], ["b", 4], ["c", 4], ["d", 1]]

It's not really a good way to count array elements, but it's kind of
an interesting illustration of some hash semantics.

David

--
David A. Black, Director
Ruby Power and Light, LLC (http://www.rubypal.com)
Ruby/Rails training, consulting, mentoring, code review
Book: The Well-Grounded Rubyist (http://www.manning.com/black2)

 Rick DeNatale 10-05-2009 11:58 AM

Re: Count the number of times an element occurs in an array

On Mon, Oct 5, 2009 at 6:14 AM, David A. Black <dblack@rubypal.com> wrote:
> Hi --
>
> On Mon, 5 Oct 2009, Jim Burgess wrote:
>
>> Hi,
>>
>> I need to count the number of times an element occurs in an array.

>
> *** DISCLAIMER ***
>
> This answer is just for fun, and because sometimes seeing useful
> techniques in strange contexts helps people learn and remember them.
>
> With that in mind... here's a
>
>>> strings = %w{a b a a c b b b c c c d }

>
> => ["a", "b", "a", "a", "c", "b", "b", "b", "c", "c", "c", "d"]
>>>
>>> hash = Hash.new {|h,k| [k, strings.count(k)] }

>
> => {}
>>>
>>> hash.values_at(*strings.uniq)

>
> => [["a", 3], ["b", 4], ["c", 4], ["d", 1]]
>
> It's not really a good way to count array elements, but it's kind of
> an interesting illustration of some hash semantics.

Or, since we don't use a key more than once one could do:

strings = %w{a b a a c b b b c c c d }

not_a_hash = lambda {|k| [k, strings.count(k)] }

strings.uniq.map {|s| not_a_hash[s]}

=> [["a", 3], ["b", 4], ["c", 4], ["d", 1]]

--
Rick DeNatale

WWR: http://www.workingwithrails.com/pers...-rick-denatale

 Jim Burgess 10-05-2009 12:22 PM

Re: Count the number of times an element occurs in an array

Cheers for the replies, they are certainly very interesting and I will
work through all of them.
However, now I'm having weird problem.

When I run the following on Linux:
a = ["a", "b", "a", "b", "b"]

a.uniq.each do |elem|
puts "#{elem}\t#{a.count(elem)}"
end

I get the expected output :
a 2
b 3

But when I run exactly the same code on Windows I get:

undefined method `count' for ["a", "b", "a", "b", "b"]:Array
(NoMethodError)

ruby -v (Linux): ruby 1.8.7 (2008-08-11 patchlevel 72) [x86_64-linux]
ruby -v (Windows): ruby 1.8.6 (2009-09-24 patchlevel 111) [i386-mswin32]

Does anyone have an idea why this could be happening.
I have tried searching for a solution with Google, but could find

--
Posted via http://www.ruby-forum.com/.

 David A. Black 10-05-2009 12:36 PM

Re: Count the number of times an element occurs in an array

Hi --

On Mon, 5 Oct 2009, Jim Burgess wrote:

> Cheers for the replies, they are certainly very interesting and I will
> work through all of them.
> However, now I'm having weird problem.
>
> When I run the following on Linux:
> a = ["a", "b", "a", "b", "b"]
>
> a.uniq.each do |elem|
> puts "#{elem}\t#{a.count(elem)}"
> end
>
> I get the expected output :
> a 2
> b 3
>
> But when I run exactly the same code on Windows I get:
>
> undefined method `count' for ["a", "b", "a", "b", "b"]:Array
> (NoMethodError)
>
> ruby -v (Linux): ruby 1.8.7 (2008-08-11 patchlevel 72) [x86_64-linux]
> ruby -v (Windows): ruby 1.8.6 (2009-09-24 patchlevel 111) [i386-mswin32]
>
> Does anyone have an idea why this could be happening.
> I have tried searching for a solution with Google, but could find

count is a post-1.8.6 method.

David

--
David A. Black, Director
Ruby Power and Light, LLC (http://www.rubypal.com)
Ruby/Rails training, consulting, mentoring, code review
Book: The Well-Grounded Rubyist (http://www.manning.com/black2)

 botp 10-05-2009 01:27 PM

Re: Count the number of times an element occurs in an array

On Mon, Oct 5, 2009 at 5:24 PM, Jim Burgess <jack.zelig@gmail.com> wrote:
> I need to count the number of times an element occurs in an array.
>

just for fun

>> a = ["a", "b", "a", "b", "b"]

=> ["a", "b", "a", "b", "b"]
>> a.group_by{|x|x}.map{|x,y| [x,y.size]}

=> [["a", 2], ["b", 3]]

kind regards -botp

 Harry Kakueki 10-05-2009 01:36 PM

Re: Count the number of times an element occurs in an array

On Mon, Oct 5, 2009 at 9:22 PM, Jim Burgess <jack.zelig@gmail.com> wrote:
> Cheers for the replies, they are certainly very interesting and I will
> work through all of them.
> However, now I'm having weird problem.
>
> When I run the following on Linux:
> a = ["a", "b", "a", "b", "b"]
>
> a.uniq.each do |elem|
> puts "#{elem}\t#{a.count(elem)}"
> end
>
> I get the expected output :
> a 2
> b 3
>
> But when I run exactly the same code on Windows I get:
>
> undefined method `count' for ["a", "b", "a", "b", "b"]:Array
> (NoMethodError)
>
> ruby -v (Linux): ruby 1.8.7 (2008-08-11 patchlevel 72) [x86_64-linux]
> ruby -v (Windows): ruby 1.8.6 (2009-09-24 patchlevel 111) [i386-mswin32]
>
> Does anyone have an idea why this could be happening.
> I have tried searching for a solution with Google, but could find
>
>
> --

This works on 1.8.6

arr = ["a", "b", "a", "b", "b"]
p arr.uniq.map{|x| [x,arr.select{|y| y == x}.length]}

#> [["a", 2], ["b", 3]]

Harry

--
A Look into Japanese Ruby List in English
http://www.kakueki.com/ruby/list.html

All times are GMT. The time now is 09:43 AM.