我有一组以一种模式重复出现的整数:
val repeatingSequence = List(1,2,3,1,2,3,4,1,2,1,2,3,4,5)
我希望在模式重复时将List列出来;在这种情况下,当序列返回1时:
val groupedBySequence = List(List(1,2,3), List(1,2,3,4), List(1,2), List(1,2,3,4,5))
请注意,当序列跳回到1时,我正在分组,但序列可以是任意长度。我和我的同事通过添加一个名为'groupWhen'
的附加方法解决了这个问题class IteratorW[A](itr: Iterator[A]) {
def groupWhen(fn: A => Boolean): Iterator[Seq[A]] = {
val bitr = itr.buffered
new Iterator[Seq[A]] {
override def hasNext = bitr.hasNext
override def next = {
val xs = collection.mutable.ListBuffer(bitr.next)
while (bitr.hasNext && !fn(bitr.head)) xs += bitr.next
xs.toSeq
}
}
}
}
implicit def ToIteratorW[A](itr: Iterator[A]): IteratorW[A] = new IteratorW(itr)
> repeatingSequence.iterator.groupWhen(_ == 1).toSeq
List(List(1,2,3), List(1,2,3,4), List(1,2), List(1,2,3,4,5))
但是,我们都觉得这里有一个更优雅的解决方案潜伏在收藏库中。
答案 0 :(得分:9)
给定一个迭代器itr
,这将解决问题:
val head = iter.next()
val out = (
Iterator continually {iter takeWhile (_ != head)}
takeWhile {!_.isEmpty}
map {head :: _.toList}
).toList
答案 1 :(得分:2)
众所周知,折叠可以做任何事情......;)
val rs = List(1,2,3,1,2,3,4,1,2,1,2,3,4,5)
val res = (rs++List(1)).foldLeft((List[List[Int]](),List[Int]()))((acc,e) => acc match {
case (res,subl) => {
if (e == 1) ((subl.reverse)::res,1::Nil) else (res, e::subl)
}
})
println(res._1.reverse.tail)
请将此视为模糊Scala竞赛的参赛作品而不是真正的答案。
答案 2 :(得分:2)
这是我使用span
打击的一个不太优雅的解决方案:
def groupWhen[A](fn: A => Boolean)(xs: List[A]): List[List[A]] = {
xs.span(!fn(_)) match {
case (Nil, Nil) => Nil
case (Nil, z::zs) => groupWhen(fn)(zs) match {
case ys::yss => (z::ys) :: yss
case Nil => List(List(z))
}
case (ys, zs) => ys :: groupWhen(fn)(zs)
}
}
scala> groupWhen[Int](_==1)(List(1,2,3,1,2,3,4,1,2,3,4,5))
res39: List[List[Int]] = List(List(1, 2, 3), List(1, 2, 3, 4), List(1, 2, 3, 4, 5))
scala> groupWhen[Int](_==1)(List(5,4,3,2,1,2,3,1,2,3,4,1,2,3,4,5))
res40: List[List[Int]] = List(List(5, 4, 3, 2), List(1, 2, 3), List(1, 2, 3, 4), List(1, 2, 3, 4, 5))
答案 3 :(得分:1)
import scala.collection.mutable.ListBuffer
import scala.collection.breakOut
val repeatingSequence = List(1,2,3,1,2,3,4,1,2,1,2,3,4,5)
val groupedBySequence: List[List[Int]] = repeatingSequence.foldLeft(ListBuffer[ListBuffer[Int]]()) {
case (acc, 1) => acc += ListBuffer(1)
case (acc, n) => acc.last += n; acc
}.map(_.toList)(breakOut)