Find the Most Frequently Occurring Element in an Array With Ruby

Two methods for iterating over an array

Dallas Bille
Feb 20 · 5 min read
Photo by Clem Onojeghuo on Unsplash

In my piece, I’ll discuss a specific task operated on an array that to me is a bit interesting and I like it. It also exemplifies the Ruby idea that there are multiple ways of performing one task and a single one isn’t considered right. Isn’t that a wonderfully accepting outlook?

Anyway, multiple times I have come across a task that required me to iterate over an array with the purpose of attempting to select the element that occurs the most in that array. And I will narrate a delightful example.

Carol is an animal hoarder. She just can’t help herself. Any stray she comes across, she has to take home. It’s a real problem.

It becomes such a problem that animal control has told her she needs to document what pets she has because she has to get rid of some of these animals. She lives in a one-bedroom apartment!

She decides she will get rid of one of the pets she has the most of. But there are so many, and she doesn’t want to count them by hand.

Here is the array of Carol's pets:

pets = [ “dog”, “dog”, “cat”, “bird”, “chinchilla”, “rat”, “hampster”, “dog”, “rat”, “bird”, “cat”, “giraffe”, “cat”, “bird”,”dog”, “snake”, “hamster”, “dog” , “mouse”, “spider”, “dog”, “cat”]

Method 1.

The first method I’ll use converts the array into a hash with values. We assume you understand how to set a hash’s keys and values. What this method does is iterates over the array, sets an element of the array as a key for the hash, and, for each element’s occurrence, increases its value by one. So if it comes across a pet that exists already in the hash, it increases that pet’s value by one, while keeping the key unique.

Here is what the first method looks like:

pet_count = Hash.new(0)
pets.each {|pet| pet_count[pet] += 1}
pet_count.sort_by { |pet,number| number}.last[0]

Let’s break it down a little bit.

pet_count = Hash.new(0)
#creates a new hash, sets its default values to 0.
pets.each {|pet| pet_count[pet] += 1}
#iterates each element, sets our empty hashes key to that of a pet. # “+=“ is the operator on the value of a keys occurrence in the hash.

(E.g., the first iteration: pet_count = {“dog” => 1 }. This is the first occurrence of “dog.”)

If our second iteration contains the same element of a key in our hash, then it adds 1 to that key’s value, while keeping the key unique, which is what happens. (E.g. the second iteration: pet_count = {“dog” => 2}. This is the second occurrence of “dog.”)

Our third iteration sets a new key and a new value since the next element in our carols_pets array is new to our hash. Our hash doesn’t contain a key of “cat” so a new key is created and a value automatically set to 1. Now our pet_count = {“dog”=>2, “cat”=> 1}.

To me this is beautiful. It touches on iteration and the structure of hash creation with key- and value-setting in a block. If you are new to operating on arrays and hashes, this is a good method to dissect. It’s also satisfying to view the result. Which is this:

pet_count = {“dog"=>6, "cat"=>3, "bird"=>3, "chinchilla"=>1, "rat"=>2, "hamster"=>2, "snake"=>1, "mouse"=>1, "spider"=>1}

As you can see, our hash is not quite in order.

Now we can operate on this hash to return the most commonly occurring pet, using the method below.

pet_count.sort_by{|pet,number| number}.last[0]
#hash gets sorted by number

Now let's break this down a little bit:

.sort_by is a hash method, and the block is what the hash gets sorted by (number of times a pet occurs).

If we just ran:

pet_count.sort_by {|pet,number| number}
#returns
[["snake", 1], ["spider", 1], ["mouse", 1], ["chinchilla", 1], ["rat", 2], ["hamster", 2], ["bird", 3], ["cat", 3], ["dog", 6]]

The default sorting with this method for integers is low to high so actually the last key-value pair is the most commonly occurring. All you have to do is call the method “last.”

pet_count.sort_by{|pet,number| number}.last
returns [“dog”=> 6]

All you have to do is add on [0], which operates on an array index number.

pet_count.sort_by{|pet,occurrences| occurrences}.last[0]
returns "dog"

There we go. We have our most popular pet. It’s a little lengthy and complicated, though.


Method 2.

This one is significantly shorter, spits out the exact answer you need, and doesn’t require you to convert the array into a hash. Which is nice as well. And I would likely use this from here on out if all I wanted was to return the pet that occurred the most.

Remember our array of Carol's pets:

pets = [ “dog”, “dog”, “cat”, “bird”, “chinchilla”, “rat”, “hamster”, “dog”, “rat”, “bird”, “cat”, “giraffe”, “cat”, “bird”,”dog”, “snake”, “hamster”, “dog” , “mouse”, “spider”, “dog”, “cat”]

Here is our method:

pets.max_by {|i| pets.count(i)}

What is going on here? A method inside a method. The inception of methods.

It returns the Object for the maximum value. If we wanted to check to see which animal had the longest name, we could use:

pets.max_by{|pet| pet.length}
returns "chinchilla"

Which is the pet with the longest name.

You’ll notice that:

chinchilla.length = 10

.max_by returns the object.

Pretty self-explanatory: It counts items in the array. If we did the following, it would return the number of items in the array, 20.

pets.count = 20

If we gave it an argument, like pets(“cat”), it returns the number of times cat shows up in the array.

pets(“cat”) = 4

When we use the following, we are simply combining these methods.

pets.max_by{|pet| pets.count(pet)} 

We know a pet object will be returned, with max_by, and each pet in the array is being counted with pets.count(pet). Each element is being iterated and counted, then max_by picks out the object that has the highest count — which is “dog.”

pets = [ “dog”, “dog”, “cat”, “bird”, “chinchilla”, “rat”, “hamster”, “dog”, “rat”, “bird”, “cat”, “giraffe”, “cat”, “bird”,”dog”, “snake”, “hamster”, “dog” , “mouse”, “spider”, “dog”, “cat”]pets.max_by {|pet| pets.count(pet)}
returns "dog"

Conclusion

Each method has its own benefits. Say you wanted more information, like how many of the most popular pet there is, the hash method is a good bet.

If you specifically want the return to be the pet and have no use for any additional information, the second method is the way to go. Just a nice single line.

So now Carol has to get rid of old Rusty. He’s a good dog, and I’m sure he’ll make some family very happy.


Resources

Here are some resources that may be helpful if you are starting out.

Get used to array and hash methods with Ruby-Doc.org

Ruby Doc Array Methods

Ruby Doc Hash Methods

Working with Hashes

More Ways!

Better Programming

Advice for programmers.

Dallas Bille

Written by

Full Stack Web Developer, Adventurer, Soccer Player/Coach

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade