Scala中列表上的模式匹配

时间:2012-10-24 21:01:26

标签: list scala pattern-matching

我对Scala列表中的模式匹配感到有些困惑。

例如。

    val simplelist: List[Char] = List('a', 'b', 'c', 'd')

    //> simplelist  : List[Char] = List(a, b, c, d)

    def simple_fun(list: List[Char]) = list match {
           case (x:Char) :: (y:List[Char]) => println(x)
           case _ => Nil
     }                                                 
   //> simple_fun: (list: List[Char])Any

   simple_fun(simplelist)                            

   //> a
   //| res0: Any = ()

目前只打印一行输出。它是否应该在列表的每个元素上运行/模式匹配?

编辑:我修复了编译错误并复制了REPL的输出。

3 个答案:

答案 0 :(得分:23)

除非你以某种方式反复调用simple_fun,否则你所拥有的将匹配第一个元素,而不是更多。为了使它与整个列表匹配,您可以让simple_fun以递归方式调用自身,如下所示:

val simplelist: List[Char] = List('a', 'b', 'c', 'd')

def simple_fun(list: List[Char]): List[Nothing] = list match {
  case x :: xs => {
    println(x)
    simple_fun(xs)
  }
  case _ => Nil 
}

注意我还遗漏了一些类型,因为Scala编译器可以推断它们,从而使代码更简洁,更易读。

作为一个小小的注释,在函数内部反复调用println并不是特别有用 - 因为它只是副作用。更惯用的方法是让函数构造一个描述列表的字符串,然后通过一次调用println输出 - 所以副作用保存在一个明确定义的位置。这样的事情就是一种方法:

def simple_fun(list: List[Char]):String = list match {
  case x :: xs => x.toString + simple_fun(xs)
  case Nil => ""
}

println(simple_fun(simple_list))

答案 1 :(得分:1)

我还想提到,列表的大小不仅可以分为头和尾,还可以分为N个列表元素:

def anyFunction(list: List[Int]): Unit =
  list match {
        // ...methods that have already been shown
      case first :: second :: Nil  => println(s"List has only 2 elements: $first and $second")
      case first :: second :: tail => println(s"First: $first \nSecond: $second \nTail: $tail")
  }

希望对某人有用。

答案 2 :(得分:0)

我认为以下内容应该有效:

def flatten(l: List[_]): List[Any] = l match {
  case Nil => Nil
  case (head: List[_]) :: tail => flatten(head) ::: flatten(tail)
  case head :: tail => head :: flatten(tail)
}

第一行是Nil的匹配,所以如果我们发现什么都没有返回。 第二行将识别列表列表并调用展平方法并展平列表列表。