【问题标题】:How to sum two neighbours in a list in scala如何在scala的列表中求和两个邻居
【发布时间】:2018-12-03 10:14:04
【问题描述】:

如果您在 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
  }
}

这是我能想到的。

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

所以 f.e.应该是:

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

而不是

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

【问题讨论】:

  • List(4, 4, 4, 2, 6) 的预期结果是什么?
  • 那就是 List(8, 4, 2, 6)
  • List(2, 4, 4, 2, 6) 怎么样?它是不变的,还是产生List(2, 8, 2, 6)?再举几个例子会有帮助。
  • 是的,那就是List(2, 8, 2, 6)

标签: scala list recursion sum pattern-matching


【解决方案1】:

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

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 )
}

【讨论】:

  • 非常感谢。似乎工作得很好。另一个问题:我将如何更改代码以便从右到左而不是从左到右迭代?所以那个 f.e.它将是 List(2, 2, 2, 6, 4) => List(2, 4, 6, 4)
  • 简单的方法就是def sumSameNeighborsFromRight( ls : List[Int] ) = sumSameNeighbors( ls.reverse ).reverse
【解决方案2】:

注意:根据最终 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)

【讨论】:

  • 如果输入刚以一个唯一的数字开头,这将中断。这个问题并没有真正提到这一点,但这可能是一个很好的假设。
  • 是的,break 是错误的词,因为只有操作人员会知道 List(9, 4, 4, 4, 2, 6) 应该返回什么。史蒂夫的结果会有所不同。
  • @XavierGuihot 这个解决方案是错误的,它不会产生正确的答案。有关List(2, 4, 4, 2, 6) 的正确转换,请参阅问题上的 cmets。
【解决方案3】:

使用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)?这产生了第二个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    • 2022-08-23
    相关资源
    最近更新 更多