2011-11-28 62 views
6

給定位置的列表的字符串,你會怎麼寫泛函實施split(positions:List[Int], str:String):List[String],這是類似splitAt而是由給定的位置列表拆分給定的字符串轉換爲字符串的列表如何分割在斯卡拉

例如

  • split(List(1, 2), "abc")返回List("a", "b", "c")
  • split(List(1), "abc")返回List("a", "bc")
  • split(List(), "abc")返回List("abc")
+1

我會使用基於'子的解決方案'而不是'splitAt'。前者將在內存中重用原始的'String',而後者則會將字符串複製到新的字符串中。提供的解決方案可以調整爲使用'substring'。 –

回答

4
def lsplit(pos: List[Int], str: String): List[String] = { 
    val (rest, result) = pos.foldRight((str, List[String]())) { 
    case (curr, (s, res)) => 
     val (rest, split) = s.splitAt(curr) 
     (rest, split :: res) 
    } 
    rest :: result 
} 
4

像這樣:

def lsplit(pos: List[Int], s: String): List[String] = pos match { 
    case x :: rest => s.substring(0,x) :: lsplit(rest.map(_ - x), s.substring(x)) 
    case Nil => List(s) 
} 

(公平的警告:不是尾遞歸,所以會把堆棧放大,由於索引和子鏈的重複重新映射,效率不高。您可以通過添加額外的參數和/或不遞歸的內部方法解決這些事情。)

+0

謝謝。我會做一個你的解決方案的尾遞歸版本。 – Michael

+2

@Michael - 可能還想考慮添加一個'startAt'索引,以便您可以使用'substring(startAt,x):: lsplit(rest,s,startAt + x)'(在非尾遞歸版本中,當然)。如果你這樣做,不要忘記'無'情況。 –

2

如何....

def lSplit(indices : List[Int], s : String) = (indices zip (indices.tail)) map { case (a,b) => s.substring(a,b) } 

scala> lSplit(List(0,4,6,8), "20131103") 
List[String] = List(2013, 11, 03)