Scala列表匹配最后一个元素

4

我目前正在学习Scala,感到非常惊奇。这种语言可以优雅地解决许多问题。但是,在匹配列表的最后一个元素时,我遇到了一个问题。

让我们来看一下这段代码:

def stringify(list: List[String]): String = list match {
  case x :: xs => x + (if (xs.length != 0) ":" else "") + stringify(xs)
  case Nil => ""
}

这样做非常不优雅,我希望写出更直观的代码,像这样:

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

我该怎么做?


@enzyme 这就是我在程序中所追求的。我不喜欢重复的代码。 - bash0r
2个回答

6

您需要交换顺序。 xs 符号将急切地匹配该位置的任何内容。尝试首先匹配 Nil 将使该语句不再无法访问。此外,您仍然需要单独匹配 Nil 以处理空列表。

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

尽管 mkString 已经可以实现您想要实现的功能。


2
这是一个很好的回答。只是要提醒该回答的作者,要小心递归。如果你可以尽量将方法编写为尾递归形式,这将允许编译器通过重用堆栈来优化实现,从而使其适用于更大的数据集。http://oldfashionedsoftware.com/2008/09/27/tail-recursion-basics-in-scala/ - Lionel Port
@LionelPort 我的目标始终是为命名优化生成尾递归。这就是我喜欢函数式编程的原因。 - bash0r

1
这是使用List#foldRight的实现方式:
 def stringify(list: List[String]): String = 
         list.foldRight(""){ 
               (e, acc) => if (acc.isEmpty) e 
                           else { e + ":" + acc } 
         }

当遍历这个列表时,我们需要检查累加器是否为空。否则,我们将在 stringfied 字符串结果的末尾得到一个额外的 :测试
scala> stringify(List("1", "2" , "3") )
res6: String = 1:2:3

scala> stringify(List("1", "2" , "3", "500") )
res7: String = 1:2:3:500

哇,这是另一种不错的方法!感谢您的启发。 - bash0r

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接