1. Introduction
Scala has a very powerful and robust collections standard library. The standard collection library provides rich and versatile data structures for processing collections of elements.
In this tutorial, we’ll look into two powerful methods, namely grouped() and sliding(). Both are part of Iterator and hence accessible to all collections such as List, Set, and so on. Additionally, the same methods are implemented in ArrayOps so that they’re also available with Array types.
2. The sliding() Method
The sliding() method allows us to create a sliding window from collection elements. It takes a group size and window size as parameters. The group size defines how many elements will be contained in each group. The window size defines how many elements we’ll shift as we traverse the collection from left to right. Let’s look at an example:
val numbers: List[Int] = List(1, 2, 3, 4, 5, 6)
val slidingWindow: Iterator[List[Int]] = numbers.sliding(2,1)
assert(slidingWindow.toList == List(List(1, 2), List(2, 3), List(3, 4), List(4, 5), List(5, 6)))
Here, we specified a group size of 2 and a sliding window size of 1. The sliding() method returns an Iterator with the list of groups.
The sliding only works from left to right. So if we want to slide from right to left, we first have to reverse the order of the elements.
We can also call sliding() by only providing the group size. The sliding window size is used as 1 in this case:
val numbers = List(1,2,3,4,5,6)
val window = numbers.sliding(2)
assert(window.toList == List(List(1, 2), List(2, 3), List(3, 4), List(4, 5), List(5, 6)))
It’s important to note that some windows may have fewer elements than specified when there are insufficient elements. Let’s look at such a case:
val numbers = List(1,2,3,4)
assert(numbers.sliding(3,2).toList == List(List(1, 2, 3), List(3, 4)))
Here, the last window has only two elements, even though we specified the window size as 3.
We should also be aware that if the group size is smaller than the sliding window size, some elements might be omitted.
The sliding() method comes in handy in scenarios such as time series data analysis, pattern matching, moving average calculations, etc.
3. The grouped() Method
The grouped() method groups a collection into smaller non-overlapping subgroups. Let’s look at it with an example:
val numbers = List(1,2,3,4)
assert(numbers.grouped(2).toList == List(List(1, 2), List(3, 4)))
However, the final group created by grouped() may have a smaller size if there are insufficient elements to fill it entirely, similar to the sliding() method.
It’s worth noting that the grouped() method behaves equivalently to the sliding() method when using the same value for both the group size and the window size:
val numbers = List(1,2,3,4,5,6)
val slidingList = numbers.sliding(2,2).toList // List(List(1, 2), List(3, 4), List(5, 6))
val groupedList = numbers.grouped(2).toList // List(List(1, 2), List(3, 4), List(5, 6))
assert(slidingList == groupedList)
The key difference between the grouped() and sliding() methods is that grouped() exclusively generates non-overlapping groups, whereas sliding() provides the flexibility to create both overlapping and non-overlapping groups of elements.
The grouped() method is very useful in scenarios such as batch processing, data transformation, etc.
4. Conclusion
In this article, we looked at two similar methods sliding() and grouped() in Scala Collections. We looked at different ways of creating sliding window groups. We also discussed the similarities and differences between these two methods.
As always, the sample code used in this article is available over on GitHub.