1. Introduction
Kotlin has a rich, efficient, and concise collection library. The standard library provides a variety of useful methods to process collection contents easily.
In this tutorial, we’ll look at two such methods, eachCount() and eachCountTo(), that help perform aggregation operations.
2. eachCount()
The eachCount() method enables us to count the occurrences of elements. Additionally, it is available in any Grouping data structures, where the keyOf() function is applicable to get the keys. It generates a Map containing the counts of the elements in each group.
Let’s look at a sample code to see this in action:
val flights = listOf("EK060", "EK531", "LH7", "LH1030", "DL47", "AI120")
val flightCount = flights.groupingBy { it.take(2) }.eachCount()
val expectedMap = mapOf("EK" to 2, "LH" to 2, "DL" to 1, "AI" to 1)
assertEquals(expectedMap, flightCount)
In the above example, we start with a list of flight numbers. Moreover, we want to get the number of flights for each of the carriers. To achieve this, we use the groupingBy() function on the list to create a Grouping instance and extract the first two letters of the flight code. Subsequently, we invoke the eachCount() method which creates a map with the number of flights per carrier.
We can achieve the same functionality using the groupBy() and mapValues() functions as well:
val flights = listOf("EK060", "EK531", "LH7", "LH1030", "DL47", "AI120")
val flightCount = flights.groupBy { it.take(2) }.mapValues { it.value.count() }
val expectedMap = mapOf("EK" to 2, "LH" to 2, "DL" to 1, "AI" to 1)
assertEquals(expectedMap, flightCount)
However, this approach is more verbose, whereas the eachCount() approach is more readable.
This is very useful in creating a frequency map from collection data.
3. eachCountTo()
The eachCountTo() function is very similar to the eachCount() function. While eachCount() generates a new immutable map with the counts of elements in the collection, eachCountTo() serves a slightly different purpose. It takes a mutable map as a parameter and combines the count from the input collection with the passed parameter. Essentially, eachCountTo() updates the counts onto the destination mutable map, making it a good choice in scenarios where we want to accumulate the counts continuously.
Let’s modify the previous example with the use of the eachCountTo():
val flights = listOf("EK060", "EK531", "LH7", "LH1030", "DL47", "AI120")
val flightCount = flights.groupingBy { it.take(2) }.eachCount().toMutableMap()
val expectedMap = mutableMapOf("EK" to 2, "LH" to 2, "DL" to 1, "AI" to 1)
assertEquals(expectedMap, flightCount)
val moreFlights = listOf("EK061", "AI435")
moreFlights.groupingBy { it.take(2) }.eachCountTo(flightCount)
val expectedMapAfterMoreFlights = mutableMapOf("EK" to 3, "LH" to 2, "DL" to 1, "AI" to 2)
assertEquals(expectedMapAfterMoreFlights, flightCount)
Here, the initial part of the example is similar to the previous case, except for the conversion to a mutable map. Subsequently, we use this mutable map and pass it as a parameter to eachCountTo(), which efficiently updates the counts within the map.
4. Conclusion
In this article, we explored two useful functions from the Kotlin standard library, eachCount() and eachCountTo(). These functions simplify the counting operations, providing enhanced readability and efficiency.
As always, the sample code used in this tutorial is available over on GitHub.