2015-11-05 39 views
0

说我有一个项目列表:斯卡拉:发现列表中的所有连锁

Seq(A, B, B, B, B, G, G, S, S, S, B, A, G)

而且我想找到所有的连锁店,让他们像这样的顺序:

Seq(Seq(A), Seq(B, B, B, B), Seq(G, G), Seq(S, S, S), Seq(B), Seq(A), Seq(G))

我想保持顺序,并使用自定义比较函数来确定两个对象是否“相同”。我在想折叠或扫描可能是我需要的,但我无法提出确切的案例。我正在使用Scala。

编辑:我已经修改了答案从类似的问题,得到这个:

def collapse(input: Seq[Stmt]): Seq[Seq[Stmt]] = { 
    val (l, r) = input.span(_.getClass == input.head.getClass) 
    l :: collapse(r) 
} 
+2

[拆分串分成组(的可能的复制http://stackoverflow.com/questions/5248065/splitting-string-into-groups) – Haspemulator

回答

2

清洁的解决方案:

def pack[T](input: List[T]): List[List[T]] = 
    input.foldRight(Nil : List[List[T]]) ((e, accu) => accu match { 
     case Nil => List(List(e)) 
     case [email protected](h :: t) if e == h => List(e) :: curList 
     case [email protected](h :: t) => List(List(e)) ::: curList 
    }) 

不使用任何库函数(丑):

def pack[T](input: List[T]): List[List[T]] = { 
    def packWithPrevious(remaining: List[T])(previous: List[T]): List[List[T]] = 
     remaining match { 
     case List() => List(previous) 
     case head :: tail => 
      val nextIter = packWithPrevious(tail)(_) 
      previous match { 
      case List() => nextIter(List(head)) 
      case prevHead :: _ => 
       if (head != prevHead) 
       previous :: nextIter(List(head)) 
       else 
       nextIter(head :: previous) 
      } 
     } 
    packWithPrevious(input)(List()) 
    } 

scala> val s = List('A', 'B', 'B', 'B', 'B', 'G', 'G', 'S', 'S', 'S', 'B', 'A', 'G') 
s: List[Char] = List(A, B, B, B, B, G, G, S, S, S, B, A, G) 

scala> pack(s) 
res2: List[List[Char]] = List(List(A), List(B, B, B, B), List(G, G), List(S, S, S), List(B), List(A), List(G)) 

来源:https://github.com/izmailoff/scala-s-99/blob/master/src/main/scala/s99/p09/P09.scala

测试:https://github.com/izmailoff/scala-s-99/blob/master/src/test/scala/s99/p09/P09Suite.scala

0

考虑以下解决方案:

seq.foldLeft(List(List(seq.head))) { case (acc,item)=> 
    if(acc.head.head==item) (item::acc.head)::acc.tail else List(item)::acc 
}.reverse 

序列可能是空的,所以:

seq.foldLeft(List(seq.headOption.toList)) { case (acc,item)=> 
    if(acc.head.head==item) (item::acc.head)::acc.tail else List(item)::acc 
}.reverse 
+0

如果'seq'为空会发生什么? –

+0

每个子列表都向后,但我可以修复该问题。谢谢。另外我会添加一个空的列表检查。 – sargunster

+0

我已更新我的帖子并修复 – Nyavro

0

我想groupBy将是有益的在这里,但我的解决方案得到了略显尴尬:

val seq = Seq("A", "B", "B", "B", "B", "G", "G", "S", "S", "S", "B", "A", "G") 
val parts = { 
    var lastKey: Option[(Int, String)] = None 
    seq.groupBy(s => { 
    lastKey = lastKey.map((p: (Int, String)) => 
     if (p._2.equalsIgnoreCase(s)) p else (p._1 + 1, s)) orElse Some((0, s)) 
    lastKey.get 
    }).toSeq.sortBy(q => q._1).flatMap(q => q._2) 
} 

(使用equalsIgnoreCase作为例如用于比较函数)

1

到现有答案类似但我发现直接在foldLeft使用部分功能作为一个干净的溶液:

val s = Seq("A", "B", "B", "B", "B", "G", "G", "S", "S", "S", "B", "A", "G") 

s.foldLeft(Seq[Seq[String]]()) { 
    case (Seq(), item) => Seq(Seq(item)) 
    case (head::tail, item) if head.contains(item) => (item +: head) +: tail 
    case (seq, item) => Seq(item) +: seq 
}.reverse 

res0: Seq[Seq[String]] = List(List(A), List(B, B, B, B), List(G, G), List(S, S, S), List(B), List(A), List(G))