【问题标题】:Rewriting a sequence by partitioning and collapsing通过分区和折叠重写序列
【发布时间】:2011-03-03 22:53:02
【问题描述】:

映射顺序集合的最优雅和最简单的算法是什么,使得满足某个谓词的连续元素折叠到另一个元素中,而那些不满足谓词的元素被 1:1 映射到另一个元素中?

这是一个例子:

sealed trait A  // say the input elements are of this type
sealed trait B  // say the output elements are of this type
case class C(i: Int) extends A // these are the input elements satisfying the predicate
case class D(s: C*) extends B // they should be collapsed into this
case class E(i: Int) extends A with B // these are input elems that are left as such

给定这个输入序列:

val input  = Seq(C(1), C(2), C(3), E(4), E(5), C(6), E(7), C(8), C(9))

预期的输出是:

val output = Seq(D(C(1), C(2), C(3)), E(4), E(5), D(C(6)), E(7), D(C(8), C(9)))
//                ---------------       -    -      -       -      --------
// the dashes indicate how the sequence is regrouped (collapsed)

这是一种方法,但我不确定这是否特别优雅:

def split(xs: Seq[A]): Seq[B] = split1(Seq.empty[B], true, xs)
@annotation.tailrec def split1(done: Seq[B], test: Boolean, rem: Seq[A]) : Seq[B] = {
    val (pre, post) = rem.span { case _: C => test; case _ => !test }
    val add = if(test) {
        D(pre.collect({ case x: C => x }): _*) :: Nil
    } else {
        pre.collect({ case x: E => x })
    }
    val done2 = done ++ add
    if(post.isEmpty) done2 else split1(done2, !test, post)
}

验证:

val output2 = split(input)
output2 == output  // ok

【问题讨论】:

    标签: scala collections grouping


    【解决方案1】:

    我会为 D 添加一个方便的方法,这样您就可以“添加”另一个 C 并返回一个新的 D。然后很容易使用一个简单的 foldLeft 左右来构建一个新的 Seq。

    【讨论】:

      【解决方案2】:

      @Landei 是的,确实,这看起来是个好方法!

      val output2 = input.foldLeft(Seq.empty[B]) {
        case (res, c: C) => res.lastOption match {
          case Some(D(x @ _*)) => res.dropRight(1) :+ D((x :+ c): _*)
          case _ => res :+ D(c)
        }
        case (res, e: E) => res :+ e
      }
      
      output2 == output // ok
      

      (当然,IndexedSeq 更适合lastOptiondropRight 和追加。)

      【讨论】:

      • 你可以用init代替dropRight(1)
      猜你喜欢
      • 2011-04-10
      • 1970-01-01
      • 2010-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多