The in operator
Often you need to know whether a list holds some value: is this name on the guest list, is this item in the cart? In Kotlin you write x in list. It compares the items with x from the first one on, and gives true as soon as one matches, or false if none does.
val colors = mutableListOf("red", "green", "blue")
println("red" in colors)
println("pink" in colors)
true
false
!in for the opposite
x !in list is true when x is missing. Both forms give a Boolean, so they fit straight into an if:
if ("pink" !in colors) {
println("No pink yet")
}
No pink yet
Writing !("pink" in colors) means the same, but !in reads better.
What in really does
The in operator calls the list's contains method, so colors.contains("red") gives the same answer. Items are compared with ==, which compares contents, so text has to match exactly, including upper and lower case: "Red" in colors is false because the list holds "red".
Traps
- Case and spaces.
"water "with a trailing space is not"water". - Value, not position.
inonly says whether the value is there. To know where it is, useindexOf, which gives-1when the value is missing. - Long lists. The check looks at the items one by one, so it takes longer on a longer list. That is fine for the short lists here.
Combining checks
Because each check is a Boolean, you can join them with && (both must hold) and || (at least one must hold):
val bag = mutableListOf("map", "water", "snacks")
if ("map" in bag && "water" in bag) println("both")
if ("tent" in bag || "water" in bag) println("one of them")
both
one of them
The same operator works on lists of numbers (3 in listOf(1, 2, 3) is true) and, beyond lists, on sets, maps and strings, where 'a' in "cat" is true. And when you need the position, bag.indexOf("water") gives 1.
Objects and other collections
Since in relies on ==, it also works for your own types as long as they define equality. A data class does that for you: with data class Guest(val name: String), Guest("Ana") in guests is true when the list holds a guest with that name, even if it is a different object.
A set answers the same question with the same syntax, "a" in set, and is built for fast lookups, which pays off when the collection is large and you check it many times. For a short list like the bag, in on the list is the simplest choice.
The exercise
bag holds map, water and snacks. The first if uses in and the second uses !in. Water is in the bag, so the first message prints. There is no tent, so "tent" !in bag is true and the second message prints too.
val bag = mutableListOf("map", "water", "snacks")
if ("water" in bag) {
println("Water is packed")
}
if ("tent" !in bag) {
println("Pack a tent")
}
Water is packed
Pack a tent
If you change the starter list, the output changes with it. Add "tent" to bag and the first message still prints, but "tent" !in bag becomes false, so the second one disappears. Each if asks its own question about the list, and the two answers don't depend on each other.
A common slip is to compare the list itself with a value, as in bag == "water". A list is not a string, and the compiler rejects it with operator '==' cannot be applied to 'MutableList<String>' and 'String'. Ask the list with in instead.
Key takeaways
x in lististruewhen the list holdsx;x !in listis the opposite.- The result is a
Boolean, ready for anif. - Matching is exact, so case matters.
