Scala - Array Pattern Matching



Arrays in Scala can be used in pattern matching to decompose their elements and handle them expressively. Extending arrays with the Matchable trait ensures safe pattern matching.

Syntax

The syntax of matching is -

array match {
  // pattern matching logic
  case Array(...) =>
  // default case
  case _ =>
}

Basic Array Patterns

You can match basic arrays by their structure and contents. So, you can handle specific array shapes and values.

Example

Try following example for basic array patterns −

object Demo {
  def main(args: Array[String]): Unit = {
    val intArray: Array[Matchable] = Array(1, 2, 3).map(_.asInstanceOf[Matchable])
    val stringArray: Array[Matchable] = Array("Scala", "Java").map(_.asInstanceOf[Matchable])
    val mixedArray: Array[Matchable] = Array(1, "Scala", 3.14).map(_.asInstanceOf[Matchable])

    println(matchArray(intArray))
    println(matchArray(stringArray))
    println(matchArray(mixedArray))
  }

  def matchArray(arr: Array[Matchable]): String = arr match {
    case Array(1, 2, 3) => "Array of Int: [1, 2, 3]"
    case Array("Scala", "Java") => "Array of Strings: [Scala, Java]"
    case Array(_, "Scala", _) => "Array with Scala in the middle"
    case _ => "Unknown array"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Array of Int: [1, 2, 3]
Array of Strings: [Scala, Java]
Array with Scala in the middle

Matching Arrays with Fixed Size

You can match arrays of a specific size so that these can conform to expected lengths. This is used for validating array structures.

Syntax

The syntax is as follows -

array match {
  // logic for array with exactly 2 elements
  case Array(a, b) =>
  // logic for array with exactly 5 elements
  case Array(a, b, c, d, e) =>
  // default case
  case _ =>
}

Example

Try following example for matching fixed sized arrays -

object Demo {
  def main(args: Array[String]): Unit = {
    val smallArray: Array[Matchable] = Array(1, 2).map(_.asInstanceOf[Matchable])
    val largeArray: Array[Matchable] = Array(1, 2, 3, 4, 5).map(_.asInstanceOf[Matchable])

    println(matchFixedSizeArray(smallArray))
    println(matchFixedSizeArray(largeArray))
  }

  def matchFixedSizeArray(arr: Array[Matchable]): String = arr match {
    case Array(_, _) => "Array with exactly 2 elements"
    case Array(_, _, _, _, _) => "Array with exactly 5 elements"
    case _ => "Array with unknown size"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Array with exactly 2 elements
Array with exactly 5 elements

Pattern Matching with Array Elements

You can pattern match specific elements within arrays to extract and process values. You can name things like first, second, third, etc for array elements, like following syntax -

Syntax

Here is the syntax for pattern matching with array elements −

array match {
  // logic for arrays with three elements
  case Array(first, second, third) => 
  // default case
  case _ => 
}

Example

Try following example for pattern matching with elements of array -

object Demo {
  def main(args: Array[String]): Unit = {
    val numbers: Array[Matchable] = Array(10, 20, 30).map(_.asInstanceOf[Matchable])

    println(matchArrayElements(numbers))
  }

  def matchArrayElements(arr: Array[Matchable]): String = arr match {
    case Array(first, second, third) => s"First: $first, Second: $second, Third: $third"
    case _ => "Array does not have exactly 3 elements"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

First: 10, Second: 20, Third: 30

Matching Arrays of Different Types

You can handle arrays containing different types by pattern matching on the type of each element. There can be different types of elements in these arrays, like in following syntax -

Syntax

Here is the syntax for matching arrays of different types −

array match {
  // logic for arrays with specified types
  case Array(a: Int, b: String, c: Double) => 
  // default case
  case _ => 
}

Example

Try following example for matching array of different types of elements -

object Demo {
   def main(args: Array[String]) = {
      val mixedArray = Array(1, "Scala", 3.14)

      println(matchDifferentTypesArray(mixedArray))
   }

   def matchDifferentTypesArray(arr: Array[Matchable]): String = arr match {
      case Array(i: Int, s: String, d: Double) => s"Int: $i, String: $s, Double: $d"
      case _ => "Array does not match expected types"
   }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Int: 1, String: Scala, Double: 3.14

Handling Nested Arrays

You can match nested arrays to handle more complex data structures. Array inside array is the nested array, like given in following syntax -

Syntax

Here is the syntax for handling nested arrays −

array match {
  // logic for nested arrays
  case Array(Array(...), Array(...)) => 
  // default case
  case _ => 
}

Try following example for handling nested array -

Example

object Demo {
  def main(args: Array[String]): Unit = {
    val nestedArray: Array[Array[Matchable]] = Array(Array(1, 2), 
       Array(3, 4)).map(_.map(_.asInstanceOf[Matchable]))

    println(matchNestedArray(nestedArray))
  }

  def matchNestedArray(arr: Array[Array[Matchable]]): String = arr match {
    case Array(Array(1, 2), Array(3, 4)) => "Nested array: [[1, 2], [3, 4]]"
    case _ => "Unknown nested array"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Nested array: [[1, 2], [3, 4]]

Guards in Array Patterns

You can use guards in pattern matching to add more conditions. You can define your own conditions using guard for matching arrays, like given in following syntax -

Syntax

Here is the syntax for guards in array patterns −

array match {
  // logic with guard condition
  case Array(a, b, c) if condition => 
  // default case
  case _ => 
}

Example

Try following example of guards in array patterns -

object Demo {
  def main(args: Array[String]): Unit = {
    val numbers: Array[Matchable] = Array(10, 20, 30).map(_.asInstanceOf[Matchable])

    println(matchWithGuards(numbers))
  }

  def matchWithGuards(arr: Array[Matchable]): String = arr match {
    case Array(first: Int, second, third) if first > 5 => s"First is greater than 5: $first"
    case _ => "Array does not match guard condition"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

First is greater than 5: 10

Array Patterns with Other Patterns

You can combine array patterns with other patterns to handle more complex matching. You can combine other pattern, like given in following syntax -

Syntax

Here is the syntax for array patterns with other patterns –

(array, otherPattern) match {
  // logic for combined patterns
  case (Array(...), ...) => 
  // default case
  case _ => 
}

Example

Try following example for array patterns with other patterns -

object Demo {
  def main(args: Array[String]): Unit = {
    val mixedArray: Array[Matchable] = Array(Person("Alice", 25), Dog("Rex"))

    println(matchCombinedPatterns(mixedArray))
  }

  case class Person(name: String, age: Int) extends Matchable
  case class Dog(name: String) extends Matchable

  def matchCombinedPatterns(arr: Array[Matchable]): String = arr match {
    case Array(Person(name, age), Dog(dogName)) => s"Person: $name, Dog: $dogName"
    case _ => "Unknown pattern"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Person: Alice, Dog: Rex

Advanced Array Patterns

You can use advanced patterns to match complex and variable-length arrays.

Syntax

The syntax for advanced array pattern is as follows:

array match {
  // logic for array starting with a specific element
  case Array(first, _*) => 
  // logic for array with specific second element
  case Array(_, second, _*) => 
  // default case
  case _ => 
}

Example

Try following example for matching advanced array pattern -

object Demo {
  def main(args: Array[String]): Unit = {
    val advancedArray: Array[Matchable] = Array(1, 2, 3, 4, 5).map(_.asInstanceOf[Matchable])

    println(matchAdvancedPatterns(advancedArray))
  }

  def matchAdvancedPatterns(arr: Array[Matchable]): String = arr match {
    case Array(1, _*) => "Array starts with 1"
    case Array(_, 2, _*) => "Array has 2 as the second element"
    case _ => "Unknown pattern"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Array starts with 1

Array Pattern Matching Summary

  • You can match Arrays by structure and contents.
  • You can match arrays of specific sizes to conform to expected lengths.
  • You can also match specific elements within arrays to extract and process values.
  • Arrays containing different types can be handled by pattern matching on the type of each element.
  • You can match nested arrays, arrays with guards in pattern matching to add more conditions.
  • You can combine array patterns with other patterns to handle more complex matching.
  • You can also use advanced patterns to match complex and variable-length arrays.
Advertisements