Tuesday, April 20, 2010

How to match for the last item in a List in Scala

The flexibility of Scala's match operator continues to amaze me.

Here's one I just found tonight. In all my match code so far, I've always had conditions for an empty list (case Nil =>) and a list with at least one item, which I usually write as case item :: moreItems =>

Tonight I needed to have a different case for when there is ONLY one item in the list. I thought, "I wonder if I can put Nil on the right-hand side of the ::?" And, sure enough, as has almost always been the case when I've asked "can match do this?", the answer was yes.

object TestingObject {
def main(args: Array[String]) {
isOneItemList(List("1", "2"))
isOneItemList(List("1", "2", "3"))
isOneItemList(List("1", "2", "3", "4"))

def isOneItemList(list: List[String]) : Unit = {
println(list + " => " +
(list match {
case Nil => "Nope: it's empty"
case one :: Nil => "Yep: just one"
case one :: two :: Nil => "Nope: there's exactly two"
case _ => "Nope: there's at least three"
List() => Nope: it's empty
List() => Nope: it's empty
List(1) => Yep: just one
List(1, 2) => Nope: there's exactly two
List(1, 2, 3) => Nope: there's at least three
List(1, 2, 3, 4) => Nope: there's at least three


  1. FYI, you don't have to use :: operator for matching lists. This also works:

    list match {
    case Nil => "Nope: it's empty"
    case List(one) => "Yep: just one"
    case List(one, two) => "Nope: there's exactly two"
    case _ => "Nope: there's at least three"

    In my opinion, this makes it more clear that you are actually looking for list of one or two elements.

  2. Thanks for that, Margus!
    I've had a lot more practice with using and writing extractors since this post, so lately I think I have been doing what you suggested.
    It's funny sometimes to look back on how you did things when you were first learning.