1. Overview
When we work with Arrays, we often want to check if an array contains a given value.
In this tutorial, let’s explore how to check whether an Array contains a given element in Kotlin.
2. Introduction to the Problem
If we consider this problem carefully, we can realize that the problem can have two variants — checking whether an Array contains:
- One single given value
- Any value from a set of values
In this tutorial, we’ll address various approaches to cover these two cases.
Further, for simplicity, we’ll create assertions in unit tests to verify if our methods work as expected.
Now, let’s create a string array as an example to verify our solutions:
val myArray = arrayOf("Ruby", "Java", "Kotlin", "Go", "Python", "Perl")
As the code above shows, in Kotlin, we can easily initialize an array using the arrayOf function. Our myArray contains a few programming language names.
Next, let’s see how to check whether the array contains specific values.
3. Check if an Array Contains One Single Value
First, let’s check if the array contains one single value.
3.1. Using the any Function
Kotlin has predefined the any() extension function on the Array class.
We can pass a predicate function to the any() function, and the any() function walks through elements in the array and returns true once an element matches the given predicate.
The any() function can solve our problem if we compare the array element and the given value in the predicate function:
assertThat(myArray.any { it == "Kotlin" }).isTrue
assertThat(myArray.any { it == "Php" }).isFalse
3.2. Using the in Operator
In Kotlin, the Array class has the contains function to check if the array contains a given value. This is exactly what we’re looking for. Moreover, when we call the contains function, we can use the in operator to make the code easier to read:
assertThat("Kotlin" in myArray).isTrue
assertThat("Php" in myArray).isFalse
Therefore, if we’re checking if an array contains one single given value, using the “value in array” would be the most straightforward and idiomatic way.
Next, let’s look into how to do the checking in the second scenario.
4. Check if an Array Contains Any Value from a Set of Values
Sometimes, we’re given multiple values, and we would like to know if an array contains at least one value from them. There are a few ways to achieve that. Next, let’s see some of them in action.
4.1. Using Java’s disjoint Method
One idea to solve the problem is first converting both the array and the values to be checked into Collection types, such as Set. Then, we can check if the two sets have elements in common. If we find common elements, it means that the array contains at least one element from the given values.
Java’s Collections.disjoint method does exactly this job:
val toBeChecked1 = setOf("Scala", "Php", "whatever", "Kotlin")
val toBeChecked2 = setOf("Scala", "Php", "Javascript", "whatever")
val mySet = myArray.toSet()
assertThat(!Collections.disjoint(mySet, toBeChecked1)).isTrue
assertThat(!Collections.disjoint(mySet, toBeChecked2)).isFalse
As the code above shows, we can use Array‘s toSet extension function to quickly convert an array to a Set. When we execute the test, unsurprisedly, it passes.
4.2. Using Kotlin’s intersect Function
The Iterable class has defined the intersect function in Kotlin’s standard library. This function will return the elements contained in both collections as a Set. Moreover, the intersect function is an infix function.
Again, we can first convert both the array and the values to be checked into two Sets and then pass the two sets to the intersect function. Finally, we verify the returned Set. If it’s not empty, we know our array contains at least one of the given values.
Next, let’s create some tests to see if it works as expected:
val mySet = myArray.toSet()
assertThat((toBeChecked1 intersect mySet).isNotEmpty()).isTrue
assertThat((toBeChecked2 intersect mySet).isNotEmpty()).isFalse
The test passes if we give it a run.
4.3. Combining the any Function and the in Operator
We’ve learned that we can check whether an array contains a single given value using the any function or the in operator.
Now, we have multiple candidate values to check. We can combine the any function and the in operator to solve the problem:
assertThat(myArray.any { it in toBeChecked1 }).isTrue
assertThat(myArray.any { it in toBeChecked2 }).isFalse
As we can see in the implementation above, we’ve used the in operator in the any function’s predicate function. Unlike the intersect and the disjoint approaches, once there is a common value detected in the array and the candidate value set, the any function returns true and terminates further checking.
Of course, we can exchange the array and the candidate values’ set in the implementation above. It follows the same logic:
assertThat(toBeChecked1.any { it in myArray }).isTrue
assertThat(toBeChecked2.any { it in myArray }).isFalse
It’s worth mentioning that, apart from passing a lambda to the any function, we can also pass the contains function’s reference:
assertThat(myArray.any(toBeChecked1::contains)).isTrue
assertThat(myArray.any(toBeChecked2::contains)).isFalse
4.4. Creating an Idiomatic infix Extension Function
Now, let’s create our own extension function “containsAnyFrom” on the Array class to solve the problem:
infix fun <T> Array<T>.containsAnyFrom(elements: Collection<T>): Boolean {
return any(elements.toSet()::contains)
}
As the code above shows, since our function has only one parameter, we can add infix to the function definition to make the function call easier to read:
myArray containsAnyFrom toBeChecked1
myArray containsAnyFrom toBeChecked2
5. Conclusion
In this article, we’ve explored different solutions for checking if an array contains a given value or any value from multiple values. Further, we’ve shown which would be the idiomatic Kotlin solutions.
As always, the full source code used in the article can be found over on GitHub.