2011-10-23 3 views
5

Listオブジェクトには、セパレータ付きの文字列に変換できるmkStringメソッドがあります。しかし、ほとんどの人間の言語は、リストを列挙するときに最後の要素を別のものとして扱います。自然言語(Scala)でリストを列挙する最良の方法は何ですか?

これを達成するためのコードサイズと効率性はどのように優れていますか?たとえば、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"))) 
+2

しかし、オックスフォード・コンマはどうですか? http://en.wikipedia.org/wiki/Serial_comma –

答えて

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

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) 
} 

また、末尾再帰を利用する正確には、私が満足する機能を探しています編集:このmig

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

@axaluss速度はリストの長さによって異なります。平均リスト長が約4要素を超える場合、この2番目のバージョンはTomaszよりも高速です。そうでなければ、やや遅くなります。

+0

があなたの最速のバージョンですか? atleastその最短;) – axaluss

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

これは私自身のバージョンです: 'def naturalMakeString(list:List [Any]、sep1:String、sep2:String)= if(list.length <2)list。 mkString else list.init.mkString(sep1)+ sep2 + list.last'しかし、あなたと私の両方は短くて効率的ではありません(initとlastの使用) – baldur

+2

'x :: Nil => x'を第2のケースとして使用すると、 'case x => x.init ...'と書いてありますが、もう少し短くなっています –

8

私のテイク:

@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) 
関連する問題