合并Scala Seq

时间:2017-06-08 08:32:46

标签: scala scala-collections

我跟随Seq作为输入:

Seq(Seq(1,2),Seq(2,3),Seq(3,4),Seq(7,8),Seq(8,9))

我想从下面创建另一个Seq:

Seq(Seq(1,4),Seq(7,9))

我认为使用滑动操作(取2)并合并设置以删除重复但我不知道如何使用Seq实现它,因为它是不可变的。有人能帮助我吗?

4 个答案:

答案 0 :(得分:3)

我不确定我是否理解正确,但请尝试以下代码:

val input = Seq(Seq(1, 2), Seq(2, 3), Seq(3, 4), Seq(7, 8), Seq(8, 9))

input.flatten.groupBy(x => x).mapValues(_.size).filter{
  case (key, value) => value == 1
}.keySet.toList.sorted.grouped(2).toList

这样的输出是:

input: Seq[Seq[Int]] = List(List(1, 2), List(2, 3), List(3, 4), List(7, 8), List(8, 9))

res0: List[List[Int]] = List(List(1, 4), List(7, 9))

答案 1 :(得分:1)

如果我理解正确,您希望删除所有连续的重复值,这样如果您有Seq(..., (a, b), (b, c), ...),则返回Seq(..., (a, c), ...)

如果你的内部Seq中总是有两个元素,你应该使用成对而不是Seq(因为在编译时尽可能多的信息应该在类型中给出),所以我会成对做,希望你能够在需要的时候进行调整。

def merge(l: Seq[(Int, Int)], acc: Seq[(Int, Int)] = Seq()): Seq[(Int, Int)] = l match {
  //if there's less than one element left, nothing can be merged
  case Seq() | Seq(_) => acc ++ l
  //if the first two elements are mergeable, merge them and call recursively (to allow merging the new pair with the next element)  
  case (a, b) +: (c, d) +: tail if b == c => merge((a, d) +: tail, acc)
  //if the first two elements are not mergeable, put the first one in the accumulator, and carry on
  case p +: tail => merge(tail, acc :+ p)
}

您可以用foldLeft替换这个尾递归函数,但我发现它更具可读性。

答案 2 :(得分:0)

Cyrille Corpet答案的foldLeft版本,坚持使用(Int, Int)对:

val data = Seq(Seq(1, 2), Seq(2, 3), Seq(3, 4), Seq(7, 8), Seq(8, 9))
  .map(s => (s.head, s.last)) // Seq((1, 2), (2, 3), ...)

val merged = data.foldLeft(Seq[(Int, Int)]())((acc, e) =>
  acc match {
    case (a, b) +: tail if (b == e._1) => (a, e._2) +: tail
    case head +: tail => e +: acc
    case Nil => Seq(e)
}).reverse  // Seq((1, 4), (7, 9))

val mergedToSeq = merged.map(s => Seq(s._1, s._2)) // Seq(Seq(1, 4), Seq(7, 9))

答案 3 :(得分:0)

更通用的Seq解决方案可能是:

val data = Seq(Seq(1,2),Seq(2,3),Seq(3,4),Seq(7,8),Seq(8,9))
val merged = data.foldLeft(Seq.empty[Seq[Int]]) {
  case (acc :+ (last :+ tail), head :: e)
    if tail == head => acc :+ (last ++ e)
  case (acc, e) => acc :+ e
} //List(List(1, 4), List(7, 9))