枚举自然语言列表(Scala)的最佳方法是什么?

时间:2011-10-23 17:32:17

标签: scala scala-collections

List对象具有mkString方法,该方法可以转换为带分隔符的字符串。但是,大多数人类语言在枚举列表时会将最后一个元素视为不同。例如A,B,C和D.

在代码大小和合理效率方面,最好的是什么?确切地说,我正在寻找满足以下条件的函数:

assertEquals("",foo(List()))
assertEquals("A",foo(List("A")))
assertEquals("A and B",foo("List("A","B")))
assertEquals("A, B and C", foo(List("A","B","C")))
assertEquals("A, B, C and D", foo(List("A","B","C","D")))

3 个答案:

答案 0 :(得分:9)

def foo(xs: List[String]) = 
  (xs.dropRight(2) :\ xs.takeRight(2).mkString(" and "))(_+", "+_)

编辑:这可能会更清楚一点:

def foo(xs: List[String]) = 
  (xs.dropRight(2) :+ xs.takeRight(2).mkString(" and ")).mkString(", ")

@axaluss速度取决于列表长度。平均列表长度大约超过4个元素,第二个版本比Tomasz更快。否则,它会稍微慢一些。

答案 1 :(得分:8)

我的看法:

def foo[T](list: List[T]): String = list match {
    case Nil => ""
    case x :: Nil => x.toString
    case x :: y :: Nil => x + " and " + y
    case x :: rs => x + ", " + foo(rs)
}

还要利用尾递归:

@tailrec def str[T](cur: String,  list: List[T]): String = list match {
    case Nil => cur
    case x :: Nil => cur + x
    case x :: y :: Nil => cur + x + " and " + y
    case x :: rs => str(cur + x + ", ", rs)
}

def foo[T](list: List[T]) = str("", list)

答案 2 :(得分:4)

def foo(list: List[String]) = list match{
  case Nil => ""
  case _ if list.length == 1 => list.first
  case _ => list.init.mkString(", ") + " and " + list.last
}