如何将元组声明为函数的返回类型以及如何在scala中调用调用者代码中的元组?

rjc*_*rjc 7 scala

假设我有一个scala函数,它应该返回一个类型的元组 (String, Int, Int) mapped to keys (words, row, col):

def getResult(param: Int)    {

// a lot of logic goes here to generate tuple values

// now return the tuple

}
Run Code Online (Sandbox Code Playgroud)

在来电代码中:

var words, row, col
if(someValue) {

  getResults(someValue)  // assigns the tuple values to keys words, row and col
  // reference words, row and col variables here

} else
  getResults(someOtherValue)  // assigns the tuple values to keys words, row and col
// reference words, row and col variables here
}
// in this scope here words, row and col are defined  and must have values that got assigned in above code
// do something more with words, row and col variables.
Run Code Online (Sandbox Code Playgroud)

代码不完整.那么我将如何声明并返回函数中的元组以及如何在上面的场景中使用?

即使地图看起来更合适,在上面的情况下是元组推荐的方式吗?

尽管我得到了所有的答案,没有答案已经解决了的我怎么申报的元组,后来填补元组中的代码(不分配值的时候声明元组这样的回答表明了问题:

var (words, row, col) =  if(someValue) {
  getResults(someValue)
} else {
  getResults(someOtherValue)
}
Run Code Online (Sandbox Code Playgroud)

这是代码的一部分仍然没有答案:

var words, row, col  // how do I delcare tuple here?
    if(someValue) {

      getResults(someValue)  // assigns the tuple values to keys words, row and col
             // how I do that here ?
      // reference words, row and col variables here

    } else
      getResults(someOtherValue)  // assigns the tuple values to keys words, row and col
    // reference words, row and col variables here
    }
Run Code Online (Sandbox Code Playgroud)

And*_*yle 19

可以以语法简单的方式(依赖于Tuple类型的unapply方法)执行多个赋值,如下所示:

val (foo, bar) = ("Hello", "world")

// The above is entirely equivalent to:
// val foo = "Hello"
// val bar = "world"
//
// or:
//
// val tmp = ("Hello", "world")
// val foo = tmp._1
// val bar = tmp._2
Run Code Online (Sandbox Code Playgroud)

因此,您只需将后一个示例更改为:

var (words, row, col) =  if(someValue) {
  getResults(someValue)
} else {
  getResults(someOtherValue)
}
Run Code Online (Sandbox Code Playgroud)

if语句将返回一个(String, Int, Int)和相关组件将被分配到words,rowcol为了.

如果您询问如何使用返回类型注释方法声明,那也很容易:

def getResult(param: Int): (String, Int, Int) = {
   ...
}
Run Code Online (Sandbox Code Playgroud)

至于它是否更好地作为地图 - 完全取决于你的方法的语义.您是一次返回多个值(元组)还是返回键和值(地图)之间的关联?无论哪个人感觉最自然和最方便的是你应该使用的(至少在没有其他顾虑的情况下).

  • @rjc,我认为@ andrzej-doyle完全回答了你的问题. (2认同)
  • @rjc:您应该考虑重构代码.在Andrzej提出的`if else`中可以发生很多事情...... (2认同)

Rex*_*err 6

首先,您需要决定是否需要地图.

你可能想要一张地图,因为

  1. 每次都会获得不同的键值对
  2. 你有很多关键值对,需要迭代它们来管理它们
  3. 您将键值作为数据,而不仅仅是代码的一部分,并且需要检索相应的值

到目前为止,它看起来并不像这三种情况中的任何一种.因此,您不需要地图,只需要为不同类型的数据命名.(也就是说,您可以让编译器处理您的名称和相应数据之间的映射.)

获取命名值的最直接方法是使用case类:

case class Result(words: String, row: Int, col: Int) {}
Run Code Online (Sandbox Code Playgroud)

你可以退货:

def getResult = Result("an example", 1, 10)
Run Code Online (Sandbox Code Playgroud)

您可以指定:

val result = getResult
Run Code Online (Sandbox Code Playgroud)

并看看部分:

println(result.words)  // Prints "an example"
Run Code Online (Sandbox Code Playgroud)

您可以为各个部分分配单独的变量:

val Result(w,r,c) = getResult    // Now w=="an example", r==1, w==10
Run Code Online (Sandbox Code Playgroud)

你可以模式匹配找到部分答案:

getResult match {
  case Result(_,1,c) => println("Had 1 row and "+c+" columns)
  case _ => println("I don't know what to do with this")
}
Run Code Online (Sandbox Code Playgroud)

您可以按名称进行复制和更改:

getResult.copy(words = "another example")
Run Code Online (Sandbox Code Playgroud)

等等.

如果您不需要名称,则可以使用以相同方式工作但仅了解参数位置的元组.第一个项目被调用_1,第二个项目被调用,_2依此类推.您只需在括号中列出项目即可指定这些内容:

def getResult = ("an example", 1, 10)
Run Code Online (Sandbox Code Playgroud)

你可以做以上所有事情,除了使用基于位置的名字:

println(getResult._3)   // Prints 10
Run Code Online (Sandbox Code Playgroud)


Dan*_*mon 5

当你有一个需要返回多个值的函数并且那些值不需要作为结构保持在一起时,元组作为返回值是有用的(如果它们需要保持在一起,那么定义一个简单的更有意义案例类).

要声明一个以3元组作为返回类型并返回3元组的函数,您可以:

def getResults(param: Int) : (String, Int, Int) = {
  ...
  (stringval, intval1, intval2)
}
Run Code Online (Sandbox Code Playgroud)

这实际上是语法糖:

def getResults(param: Int) : Tuple3[String, Int, Int] = {
  ...
  new Tuple3[String,Int,Int](stringval, intval1, intval2)
}
Run Code Online (Sandbox Code Playgroud)

Scala有N:1到22的TupleN类


Sha*_*nds 2

我是否正确地假设您希望首先声明结果变量(并且需要在 if/else 构造之外访问它们),然后调用设置和使用它们的代码(在 if/else 构造内部)?如果是这样,它应该像这样简单

var words: String = _
var row: Int = _
var col: Int = _
...
if (someValue) {
  val (words, row, col) = getResults(someValue)
  // use words, row, col
  // Note: keyword 'val' added per comments by Prometheus and John Threepwood below
} else {
  val (words, row, col) = getResults(someOtherValue)
  // use words, row, col
  // Note: keyword 'val' added per comments by Prometheus and John Threepwood below
}
Run Code Online (Sandbox Code Playgroud)

  • 当尝试在“(words, row, col) = getResults(...)”行中重新分配变量“words”、“row”和“col”时,此解决方案会在 Scala 2.9.1 中引发错误。 (2认同)