【问题标题】:Hard Time in understanding the Scala code which returns indices of the two numbers很难理解返回两个数字索引的 Scala 代码
【发布时间】:2020-04-24 12:14:27
【问题描述】:

我很难理解下面代码中的 m.getm+(x._1 -> x._2) ,谁能告诉我是什么会的

object Solution {
    def twoSum(nums: Array[Int], target: Int): Array[Int] = {
      nums.zipWithIndex.foldLeft(Map.empty[Int,Int])((m,x)=>
      {
          if(m.get(target - x._1)==None)
              m+(x._1 -> x._2)
        else
            return Array(m.getOrElse(target-x._1, -1), x._2)
    })
    null
  }
}

此代码返回两个数字的索引,以便它们相加为特定目标。

【问题讨论】:

  • mMapm.get(key) 从包裹在Option 中的Map 中检索一个值。如果Map 包含指定的键,则结果为Some(value),否则结果为Nonem+(k->v)Map 添加一个新的键-> 值对。 (注意:这不是好的/惯用的 Scala 代码。)
  • 该代码在 Scala 中远不是惯用的。不管怎样,get,正如documentation 解释的那样,试图从给定键的映射中提取一个值,但是由于键可能不存在,它返回包装在 Option 中的值.
  • 最后,m + (x._1, x._2) 正在向地图添加一个新的 key-value 对。 -> 创建一个新元组,._1._2 正在访问元组 x 的元素(所以如果你比编写代码的人有更多的大脑,你会注意到所有这些都是不必要的,因为它与 m + x) 完全相同。.
  • 感谢您的明确解释@Luis Miguel Mejía Suárez 的帮助

标签: scala scala-collections


【解决方案1】:

这里有几种不同的(更好的?)方法可以获得相同的结果(基本上相同)。

如果您想要其值总和为目标的所有索引对。

def twoSum(nums :Array[Int], target :Int) :Iterator[Seq[Int]] =
  nums.indices
      .combinations(2)
      .filter{case Seq(a,b) => nums(a) + nums(b) == target}

twoSum(Array(3,5,11,2,13,9), 41)  //returns empty Iterator
twoSum(Array(3,5,11,2,13,9), 14)  //returns Iterator(Seq(0, 2), Seq(1, 5))

如果您只想要总和为目标的第一对(提前终止)。

def twoSum(nums :Array[Int], target :Int) :Option[Seq[Int]] =
  nums.indices
      .combinations(2)
      .find{case Seq(a,b) => nums(a) + nums(b) == target}

twoSum(Array(3,5,11,2,13,9), 41)  //returns None
twoSum(Array(3,5,11,2,13,9), 14)  //returns Some(Seq(0, 2))

如果您想避免 Option,并且如果没有 2 个值与目标相加,则只返回一个空集合。

def twoSum(nums :Array[Int], target :Int) :Seq[Int] =
  nums.indices
      .combinations(2)
      .find{case Seq(a,b) => nums(a) + nums(b) == target}
      .getOrElse(Seq())

twoSum(Array(3,5,11,2,13,9), 41)  //returns Seq()
twoSum(Array(3,5,11,2,13,9), 14)  //returns Seq(0, 2)

【讨论】:

  • 为什么我在第 21 行收到错误:错误:类型不匹配; (在solution.scala中)
  • 所有三个解决方案在发布之前都经过了测试 (Scala 2.13.1)。请注意,每个解决方案的返回类型都不同。
【解决方案2】:

这是解决该问题的更有效和惯用的方法。

def twoSum(nums: ArraySeq[Int], target: Int): Option[(Int, Int)] = {
  val allIndexes = for {
    i <- Iterator.range(start = 0, end = nums.length)
    j <- Iterator.range(start = i + 1, end = nums.length)
  } yield i -> j

  allIndexes.find {
    case (i, j) => (nums(i) + nums(j)) == target
  }
}

(注意: ArraySeq 与任何普通数组一样,但它是不可变的,它是在 2.13 中引入的,如果您在旧版本中,只需使用常规 @ 987654324@).

【讨论】:

  • 非常感谢您的回复
【解决方案3】:

这是我自己的看法,该函数循环遍历所有数字对,直到找到答案。它利用了 scala 的优化递归能力。此外,它仅使用对初学者有用的简单概念:函数、数组、整数和 if-else 语句。

def twoSum(nums :Array[Int], target : Int): Array[Int] = {
    def iter(a:Int, b: Int): Array[Int] = {
        if(nums(a) + nums(b) == target) Array(a,b) 
        else if(b < nums.length-1) iter(a,b+1)  
        else iter(a+1,a+2)
    }
    iter(0,1) 
}  

jwvh:是的。失败时为空数组:

def twoSum(nums: Array[Int], target: Int): Array[Int] = {
    def iter(a: Int,b: Int): Array[Int] = {
        if(nums(a) + nums(b) == target) Array(a,b) 
        else if(b < nums.length-1) iter(a,b+1)  
        else if(a < nums.length-2) iter(a+1,a+2)
        else Array()
    }
    iter(0,1)
}

【讨论】:

  • 感谢您对社区的贡献。这可能是一个正确的答案,但对您的代码提供额外的解释会很有用,以便开发人员能够理解您的推理。这对于可能不熟悉语法的新开发人员特别有用。此外,它可以帮助减少对后续问题的需求。您可以对其进行编辑以提供进一步的解释吗?
猜你喜欢
  • 2011-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-06
  • 1970-01-01
  • 1970-01-01
  • 2013-12-27
  • 1970-01-01
相关资源
最近更新 更多