2016-12-02 2 views
1

にリストを分割することは誰もが説明できます:Scalaは:サブリスト

一覧::

scala> val ls = List("P ", "PP ", "PP ", "PP ", "P ", "PP ", "PP ", "P ") 

それとも

scala> val ls = List("P", "PP", "PP", "PP", "P", "PP", "PP", "P") 

サブリスト:

List("P", "PP", "PP", "PP"), List("P", "PP", "PP"), List("P") 
サブリストでリストを分割する方法


EDITED ::私が本当に望むのは、特定の文字列が出現するたびにリストを分割することです。

TIA。

+1

何ロジックここに?長さが短くなると分割されますか? – Marth

+0

リストをエンコードする必要があります。論理があります。 1つのリスト内のすべてのアイテムの長さを変更した後など。 – Pavel

+0

ここに何かがあるかどうかチェックしてみましたか? http://www.scala-lang.org/api/current/scala/collection/immutable/List.html takeWhile、partiion、sliceメソッドを見てください。 – Pavel

答えて

1
List("P ", "PP ", "PP ", "PP ", "P ", "PP ", "PP ", "P ") 
    .scanLeft((0, Option.empty[String])) { 
    case ((count, _), "P ") ⇒ (count + 1, Some("P ")) 
    case ((count, _), s) ⇒ (count, Some(s)) 
    }.groupBy(_._1) 
    .mapValues(_.collect { case (cnt, Some(x)) ⇒ x }) 
    .toList.sortBy(_._1).map(_._2) 
2

再帰的(ではなく末尾再帰)ソリューション:

val l = List("P ", "PP ", "PP ", "PP ", "P ", "PP ", "PP ", "P ") 

def splitBy(l: List[String], s: String): List[List[String]] = { 
    l.splitAt(l.lastIndexOf(s)) match { 
    case (Nil, tail) => List(tail) 
    case (head, tail) => splitBy(head, s) :+ tail 
    } 
} 

splitBy(l, "P ") // List(List(P , PP , PP , PP), List(P , PP , PP), List(P)) 

末尾再帰バージョン:

val l = List("P", "PP", "PP", "PP", "P", "PP", "PP", "P") 

def splitBy(result: List[List[String]], l: List[String], s: String): List[List[String]] = { 
    l.splitAt(l.lastIndexOf(s)) match { 
    case (Nil, y) => List(y) ::: result 
    case (x, y) => splitBy(List(y) ::: result, x, s) 
    } 
} 

println(splitBy(Nil, l, "P")) 
4

foldLeftを使用して別のオプション:

l.foldLeft(List[List[String]]()) { 
    case (Nil, s) => List(List(s)) 
    case (result, "P ") => result :+ List("P ") 
    case (result, s) => result.dropRight(1) :+ (result.last :+ s) 
}