如何在scala列表中求和两个邻居

时间:2018-06-24 19:25:41

标签: scala list recursion sum pattern-matching

如果您在Scala中有一个Integer列表,并且想要对其进行迭代,并将每两个具有相同值的邻居相加并将其作为列表返回,那么该怎么做呢?

例如:

List(4, 4, 2, 6) => List(8, 2, 6)

我对Scala完全陌生,但是我可以想象模式匹配或映射可能会有用。

def sumSameNeighbours: List[Int] => List[Int] = {
  ls match {
    case l1::l2:ls => l1 == l2
  }
}

这是我能想到的。

编辑:我将如何更改代码以便从右到左而不是从左到右进行迭代?

所以会是:

List(2, 2, 2, 6, 4) => List(2, 4, 6, 4)

代替

List(2, 2, 2, 6, 4) => List(4, 2, 6, 4)

3 个答案:

答案 0 :(得分:4)

这非常接近您的建议,并且似乎可以正常工作:

import scala.annotation.tailrec

def sumSameNeighbors( ls : List[Int] ) : List[Int] = {
  @tailrec
  def walk( unsummed : List[Int], reverseAccum : List[Int] ) : List[Int] = {
    unsummed match {
      case a :: b :: rest if a == b => walk( rest, a + b :: reverseAccum )
      case a :: rest                => walk( rest, a :: reverseAccum )
      case Nil                      => reverseAccum.reverse
    }
  }
  walk( ls, Nil )
}

答案 1 :(得分:3)

注意: 根据最终OP的规范说明,此答案并不完全符合问题要求。

这是使用List.grouped(2)的解决方案:

list.grouped(2).toList
  .flatMap {
    case List(a, b) if a == b => List(a + b)
    case l => l
  }

该想法是将连续元素按对分组。如果这对元素具有相同的元素,则将它们的总和返回为flatMaped,否则两个元素都保持不变。

List(4, 4, 2, 6) => List(8, 2, 6)
List(2, 4, 4, 2, 6) => List(2, 4, 4, 2, 6)
List(2) => List(2)
List(9, 4, 4, 4, 2, 6) => List(9, 4, 8, 2, 6)

答案 2 :(得分:0)

使用foldRight的另一种方法,我发现在创建一个新集合时遍历集合是一种很好的默认方法:

list.foldRight(List.empty[Int]) {
  case (x, y :: tail) if x == y => (x + y) :: tail
  case (x, list) => x :: list
}

根据要求,List(2, 2, 2, 6, 4)的输出为List(2, 4, 6, 4)

我在您的示例中不清楚的主要是,如果求和产生了新的邻居,输出应该是什么:List(8, 4, 2, 2)应该变成List(8, 4, 4)还是List(16)?这将产生第二个。