Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: August 31, 2024
Scala offers a comprehensive set of collections with powerful operations for data manipulation. Sequential collections like List, ListBuffer, and ArrayBuffer are particularly useful for handling ordered data. Removing elements from these collections is a common task, and Scala provides various methods to achieve this.
In this tutorial, we’ll explore how to remove elements from both mutable and immutable sequential collections, focusing on techniques for removing both the first match and all matches of a given element.
In this section, we’ll examine ways to remove the first match of a given element from sequential collections in Scala. We’ll explore this with both immutable and mutable collections.
We can use the span() function on a collection to split it based on a predicate. Let’s look at how we can use this to remove the first match:
val input = List("abc", "def", "xyz", "abc")
val ele = "abc"
val (part1, part2) = input.span(_ != ele)
val result = part1 ++ part2.drop(1)
result shouldBe List("def", "xyz", "abc")
The span() function splits a collection into a tuple of two parts. The first part contains all elements up to the first element that matches the predicate, while the second part contains the rest of the list, starting with the matching element. If a match is found, it’ll be the first element in the second part of the tuple. To remove this element, we can drop the first element from the second part and combine the two parts to obtain a collection with the removed element. If there is no element, the second part will be empty, and the drop() function will return an empty list.
Pattern matching is a powerful concept in Scala that can be used in many scenarios to manipulate collections. We can use it to remove the first match of an element from the collection:
val input = List("abc", "def", "xyz", "abc")
val ele = "abc"
val result = input match {
case `ele` :: sub => sub
case sub => sub
}
result shouldBe List("def", "xyz", "abc")
This code checks if the first element of the list matches the element and removes it if it does; otherwise, it leaves the list unchanged. Notice the usage of backtick(`) to surround the variable in the pattern match. When we surround a variable or value with backticks in a pattern, it instructs the compiler to match against the value of that variable rather than binding the variable to a new value.
In the previous sections, we used immutable collections. Now, let’s check how to remove the first match on a mutable collection. Let’s use ListBuffer for our example:
val buffer = ListBuffer[String]("abc", "def", "xyz", "def")
buffer -= "def"
buffer shouldBe ListBuffer[String]("abc", "xyz", "def")
We used the operation -= to remove the first matching element. Alternatively, we can use the subtractOne() function, which works in the same way.
Let’s look at different ways to remove all the matches from a collection.
We can use the filter() function to remove the matching elements from a collection:
val list = List("abc", "def", "xyz", "def")
val filteredList = list.filter(_ != "def")
filteredList shouldBe List("abc", "xyz")
list.filterNot(_ == "def") shouldBe List("abc", "xyz")
The filter() method removed the matching elements and returned a new list. Alternatively, we can use the filterNot() function without using the negative condition to achieve the same result.
We can apply the same function to ListBuffer as well. However, the filter() and filterNot() methods return a new ListBuffer with the filtered elements rather than modifying the existing ListBuffer.
Another method to achieve the same result is by using the collect() function:
val input = List("abc", "def", "xyz", "def")
val ele = "def"
val result = input.collect {
case e if e != ele => e
}
result shouldBe List("abc", "xyz")
We used the collect() function with the required partial function to remove the matching elements.
We can partition a collection based on a predicate. We can use this to remove the matching element from the collection:
val input = List("abc", "def", "xyz", "def")
val ele = "def"
val (result, _) = input.partition(_ != ele)
result shouldBe List("abc", "xyz")
The partition() function returns a tuple of two elements. The first element contains the elements that match the predicate, while the second contains those that don’t. In this case, the first part contains the list without the input element.
Mutable collections such as ListBuffer and ArrayBuffer provide another way to remove the elements using the filterInPlace() function:
val buffer = ListBuffer[String]("abc", "def", "xyz", "def")
buffer.filterInPlace(_ != "def")
buffer shouldBe ListBuffer[String]("abc", "xyz")
It works similarly to the filter() function. However, instead of returning a new collection, it removes the matching elements from the existing collection.
Yet another approach to achieve this functionality is by using the foldLeft() function:
val input = List("abc", "def", "xyz", "def")
val ele = "def"
val result = input.foldLeft(List.empty[String])((acc,i) => if(i != ele) acc :+ i else acc)
result shouldBe List("abc", "xyz")
This code uses foldLeft() to create a new list by iterating through the original list and appending elements to the accumulator only if they are not equal to the given element, effectively removing all occurrences from the list.
In this article, we explored various methods for removing an element from a list, covering both single and multiple occurrences. We also applied these techniques to both immutable and mutable collections.