How to Count Specific Items in a Collection with Elixir

So, I was working on this exercise over at Exercism.io, when I stumbled up an interesting function.

To make a long story short, I needed a count of a specific character (codepoint) in a character list i.e. 'hello' contains two ls. However, this solution could apply to any collection which implements the Enumerable protocol in Elixir.

I have been reading Programming in Elixir. The author, Dave Thomas, emphasizes the use of recursion and pattern matching throughout Elixir. So, of course, I had implemented the solution using recursion and pattern matching. You can see that solution here.

You Can Count (Ha!) on Elixir

Of course, I missed the obvious. Elixir already had a very convenient function for doing exactly this: Enum.count/2.

I had anticipated that Elixir would have a function to do a straight count of all the items in a collection (which it does: Enum.count/1 doc). However, I had not considered one for looking for a specific kind of item.

Well, Enum.count/2 provides a convenient API for this exact problem. You simply pass the enumerable (in my case, the character list) and a function which takes one argument (the current item) and will return true for whatever items you want to count.

Here’s a convenient graphic to demonstrate:

Elixir Enum Count

Elixir Enum.count/2 Examples

Of course, the expression used to evaluate the current item does not need to be a simple equality operation. Here are some examples using a variety of different operators:

Count all the binaries (strings) which equal “price”:

Enum.count(["Total", "retail", "price", "$14.95"], &(&1 == "price"))
1

Pipe syntax:

["Total", "retail", "price", "$14.95"]
  |> ... # some other functions
  |> Enum.count(&(&1 == "price"))

Count all the binaries which are members of a list:

roles = ["User", "Customer", "Partner", "Admin"]
Enum.count(roles, &Enum.member?(["Admin", "Editor", "Developer"], &1))
1

Count all the binaries (strings) which match a regular expression:

Enum.count(["Total", "price", "$14.95"], &(&1 =~ ~r/\$\d+\.\d+/))
1

Count all the binaries (strings) in a list:

Enum.count([1, "list", 3], &is_binary(&1))
1

Count all the binaries (strings) in a multi-type list:

Enum.count([1, "list", 3], &is_binary(&1))
1

Count all the integers in a multi-type list:

Enum.count([1, "list", 3], &is_integer(&1))
2

Count all the integers greater than 3:

Enum.count([1,2,4,8,16,32], &(&1 > 3))
4

Read the documentation on Enum.count/2

This post is part of my series of Elixir Tutorials


Freelance Elixir & Ruby on Rails Developer Hey, I’m Adam. I’m guessing you just read this post from somewhere on the interwebs. Hope you enjoyed it.

You can also follow me on the Twitters at: @DeLongShot

2 thoughts on “How to Count Specific Items in a Collection with Elixir

  1. To count char in binaries you can also use bitstring comprehension:
    (for << <> >, c == ?l, do: 1) |> length()

    It is more efficient than converting it to a charlist, though is “uglier” hehe

    ## CountBinaryBench
    benchmark name average time
    bitstring comprehension 4.05 µs/op
    converting to charlist 12.46 µs/op

    benchmark using: https://github.com/alco/benchfella

Comments are closed.