Peter Becker
Peter Becker

Reputation: 431

How to find the unique elements, and the occurrrence count of each one, in an array in Ruby

I have an array with some elements. How can I get the number of occurrences of each element in the array?

For example, given:

a = ['cat', 'dog', 'fish', 'fish']

The result should be:

a2 #=> {'cat' => 1, 'dog' => 1, 'fish' => 2}

How can I do that?

Upvotes: 43

Views: 31427

Answers (12)

Alexey Kharchenko
Alexey Kharchenko

Reputation: 1032

['cat','dog','fish','fish'].group_by(&:itself).transform_values(&:count)
=> {
     "cat" => 1,
     "dog" => 1,
    "fish" => 2
}

Upvotes: 3

Shan
Shan

Reputation: 653

Ruby 2.7 has tally method for this.

tally → a_hash

Tallies the collection, i.e., counts the occurrences of each element. Returns a hash with the elements of the collection as keys and the corresponding counts as values.

['cat', 'dog', 'fish', 'fish'].tally  

=> {"cat"=>1, "dog"=>1, "fish"=>2}

Upvotes: 16

Harry Joy
Harry Joy

Reputation: 59694

Use the count method of Array to get the count.

a.count('cat')

Upvotes: 4

RameshVel
RameshVel

Reputation: 65887

You can use Enumerable#group_by to do this:

res = Hash[a.group_by {|x| x}.map {|k,v| [k,v.count]}]
#=> {"cat"=>1, "dog"=>1, "fish"=>2}

Upvotes: 44

wallerdev
wallerdev

Reputation: 291

a2 = a.reduce(Hash.new(0)) { |a, b| a[b] += 1; a }
#=> {"cat"=>1, "fish"=>2, "dog"=>1}

Upvotes: 27

Michael Kohl
Michael Kohl

Reputation: 66867

In 1.9.2 you can do it like this, from my experience quite a lot of people find each_with_object more readable than reduce/inject (the ones who know about it at least):

a = ['cat','dog','fish','fish']
#=> ["cat", "dog", "fish", "fish"]

a2 = a.each_with_object(Hash.new(0)) { |animal, hash| hash[animal] += 1 }
#=> {"cat"=>1, "dog"=>1, "fish"=>2}

Upvotes: 8

look
look

Reputation: 677

a = ['cat','dog','fish','fish']
a2 = Hash.new(0)
a.each do |e|
    a2[e] += 1
end
a2

Upvotes: 1

boulder_ruby
boulder_ruby

Reputation: 39763

ruby fu!

count = Hash[Hash[rows.group_by{|x| x}.map {|k,v| [k, v.count]}].sort_by{|k,v| v}.reverse]

Upvotes: 0

u2ix
u2ix

Reputation: 622

a2 = {}
a.uniq.each{|e| a2[e]= a.count(e)}

Upvotes: 10

detunized
detunized

Reputation: 15299

a = ['cat','dog','fish','fish']
a2 = Hash[a.uniq.map {|i| [i, a.count(i)]}]

Upvotes: 3

fl00r
fl00r

Reputation: 83680

a.inject({}){|h, e| h[e] = h[e].to_i+1; h }
#=> {"cat"=>1, "fish"=>2, "dog"=>1}

or n2 solution

a.uniq.inject({}){|h, e| h[e] = a.count(e); h }
#=> {"cat"=>1, "fish"=>2, "dog"=>1}

Upvotes: 3

thekindofme
thekindofme

Reputation: 3866

m = {}

a.each do |e|
  m[e] = 0 if m[e].nil?
  m[e] = m[e] + 1
end

puts m

Upvotes: 3

Related Questions