Is this value in the buffer?
Programs often need to know whether a collection holds a value: is this name on the guest list, is this item in the cart? On an ArrayBuffer the answer comes from contains(x). It compares the items with x from the first one on, and returns true as soon as one matches or false if none does.
val colors = scala.collection.mutable.ArrayBuffer("red", "green", "blue")
println(colors.contains("red")) // true
println(colors.contains("pink")) // false
Scala has no in keyword for this. You ask the collection itself.
Using it in an if
The result is a Boolean, so it works directly as the condition of an if:
val cart = scala.collection.mutable.ArrayBuffer("milk", "bread")
if (cart.contains("milk")) {
println("Milk is in the cart")
}
Put ! in front to turn the answer around. !cart.contains("eggs") is true when the cart has no eggs:
if (!cart.contains("eggs")) {
println("No eggs yet")
}
Things to watch
- Text must match exactly.
colors.contains("Red")isfalse, because the buffer holds"red". Upper and lower case are different characters. - It checks whole items.
colors.contains("re")isfalsetoo: no item equals"re", even though"red"starts with it. - The type of the value matters. In a buffer of numbers such as
ArrayBuffer(1, 2, 3),contains(2)istrue. Asking for the text"2"still compiles, but it isfalse, because a number never equals a string. - Only equality.
containsasks "is there an item equal to x?". For a different question, such as "is there an item above 2?", useexists:nums.exists(_ > 2).
Why check first
Asking before acting keeps a program from doing the same thing twice. A guest list that already has a name shouldn't get it again, and a message such as "Pack a tent" should only appear when there is no tent. In both cases the code reads the same way: a question that gives true or false, then an if that acts on the answer. Because contains starts at the first item and stops at the first match, it is quick on short buffers like these. On a very long buffer with no match it has to look at every item.
Two checks, two answers
Each if is independent. In the task below, both lines can print, only one can, or neither, depending on what is in the bag. Nothing links them, and an else is not needed because the two questions are about different values. Use else only when one question has two outcomes.
The task
bag holds what is packed for a hike. Print Water is packed if "water" is in the bag, and Pack a tent if "tent" is not.
- Write an
ifwhose condition isbag.contains("water"). The bag has water, so the condition is true and the first line prints. - Write a second
ifwith!bag.contains("tent"). The bag has no tent, socontainsgivesfalse,!makes ittrue, and the second line prints.
val bag = scala.collection.mutable.ArrayBuffer("map", "water", "snacks")
if (bag.contains("water")) {
println("Water is packed")
}
if (!bag.contains("tent")) {
println("Pack a tent")
}
It prints:
Water is packed
Pack a tent
Key takeaways
buf.contains(x)istruewhen some item equalsx, otherwisefalse.- Use it as an
ifcondition; add!to test for a missing value. - The match is exact, including case, and it is about whole items.
