【问题标题】:passing variable argument data type to a scala method将变量参数数据类型传递给 scala 方法
【发布时间】:2017-01-24 18:51:45
【问题描述】:

我想在 scala 中创建一个方法/函数,它可以接受 string 或 int 类型的变量参数并返回 String 或 Int 类型的结果。

def Hello(name: String, Param: int*/string*): Int/String= {

var index = 0

while(index < Param.length) {

var n = name

var ar = Param(index)

if ( n.equals(ar) ) return Param(index + 1) 

else index = index + 1

}

return Param(index.length -1)

}

如果我们调用 Hello 函数,那么它应该返回如下所示的结果。

val Res1 = Hello("Jack", "rakesh", 1, "Jack", 2, "No one") 

println(Res1)

=> this should return value 2

val Res2 = Hello("ABC", "rakesh", 1, "Jack", 2, "Vik", 3, "ram", 4, "No one") 

println(Res2)

=> this should return value "No one"

【问题讨论】:

  • 可能使用Any 会有所帮助,但不准确? def func1(a: String, s: Any*): Any
  • 你考虑过Ether吗? def Hello(name: String, Param: Either[Array[Int]/Array[String]]): Either[Int/String]?您可以为可变参数重载它,并在函数中使用Either 的通用代码。

标签: scala


【解决方案1】:

使用Any 应该可以工作:

def hello(name: Any, param: Any*): Any= {
    var list = param.dropWhile(_ != name)
    list.drop(1).headOption.orElse(param.lastOption).getOrElse("")
}

根据您希望它的类型安全程度,您可以尝试使用泛型或其他方式来限制使用的类型。或者你可以只匹配响应类型:

hello("ABC", "rakesh", 1, "Jack", 2, "Vik", 3, "ram", 4, "No one") match {
  case i: Int => println("Got a int:" + i)
  case s: String=> println("Got a string:" + s)
}

【讨论】:

  • 1.它不适用于这种情况:val Res3 = Hello(5, "rakesh", 1, "Jack", 2, "Vik", "vinccent", "ram", 4, 5, "Five", "No one") ==&gt; return "five"See the first comment。 2.在这种情况下抛出异常:Hello("No one", "rakesh", 1, "Jack", 2, "Vik", 3, "ram", 4, "No one")
  • @zhelezoglo 看到我更新的答案,我简化了代码。当它找不到元素时,我返回最后一个元素。不确定您是否要将其更改为其他内容
【解决方案2】:

这对你有帮助

def Hello( name: String,args: Any* ) = {

      val index = args.indexOf(name)
      if(index == -1)
        args(args.length - 1)            
      else
      args(index + 1)

 } 

【讨论】:

    【解决方案3】:

    你的整个方法是错误的,但这里是如何以类型安全的方式完成的。

    def Hello(name: String, param: Either[Int,String]*): Either[Int,String] = {
      param.sliding(2,2)
           .find(_(0).fold(_ => false, _ == name))
           .fold(param.last)(_(1))
    }
    

    用法:

    Hello("Jack", Right("rakesh"), Left(1), Right("Jack"), Left(2), Right("No one"))
    // res0: Either[Int,String] = Left(2)
    
    Hello("ABC", Right("rakesh"), Left(1), Right("Jack"), Left(2),
                 Right("Vik"), Left(3), Right("ram"), Left(4), Right("No one"))
    // res1: Either[Int,String] = Right(No one)
    

    但最好从头开始重新考虑。

    【讨论】:

      【解决方案4】:

      我相信,您想要实现的是在可变参数中获取 String 元素的索引(如果从 1 开始计数),或者返回 "No one"。无需将索引传递给该方法。你可以这样做:

      def hello(name: String, params: String*): Any = {
        val idx = params.indexOf(name)
        if (idx != -1) idx + 1 else "No One"
      }
      

      不幸的是this

      def Hello(name: String, args: Any* ) = {
        val index = args.indexOf(name)
        if(index == -1)
          args(args.length - 1)
        else
          args(index + 1)
      }
      

      this:

      def hello(name: String, param: Any*): Any= {
        var index = 0
        while(index < param.length) {
          var n = name
          var ar = param(index)
          if ( n.equals(ar) ) return param(index + 1)
          else index = index + 1
        }
        param(index -1)
      }
      

      已损坏,因为如果您尝试查找"No one" 的索引,它们会抛出异常,因为index + 1 将等于数组的大小。最好将 Scala 中的事物与 == 进行比较以获得逻辑相等性。

      但最好不要返回Any,而是返回Option[Int]

      def hello(name: String, params: String*): Option[Int] =
        Option(params.indexOf(name)).filter(_ != -1).map(_ + 1)
      

      那么你可以像这样使用它:

      val message1 = hello("Jack", "rakesh" ,"Jack").getOrElse("No one")
      val message2 = hello("ABC", "rakesh", "Jack", "Vik", "ram").getOrElse("No one")
      

      回复评论:

      我想知道如何将混合数据类型传递给“参数”。

      最简单的方法是将它们全部设为Any

      还可以获取字符串或整数作为返回类型

      同理,定义返回类型为Any

      这里唯一的小问题是不会针对其他类型进行编译时检查。例如。有人可能会将Boolean 或任何复杂对象连同String's 和Int's 传递给您的函数。但是您可以在运行时检查它或使用类型来限制它们。我不知道您在这里的要求,也许这对您来说甚至是优势。

      如果有Any 没问题,那么我会这样解决:

      def Hello(name: Any, params: Any*): Any = Option(params)
        .withFilter(_.nonEmpty)
        .map(_.indexOf(name))
        .filter(i => i != -1 && i < params.length - 1)
        .map(i => params(i + 1))
        .getOrElse("No one")
      

      或者,如果您可以假设,params 永远不会为空,您必须使用最后一个参数作为默认值,而不是硬编码 "No one"

      def Hello(name: Any, params: Any*): Any = Option(params)
        .withFilter(_.nonEmpty)
        .map(_.indexOf(name))
        .filter(i => i != -1 && i < params.length - 1)
        .map(i => params(i + 1))
        .getOrElse(params.last)
      

      注意检查"No one" 攻击:i &lt; params.length - 1。 请注意,name 现在也是 Any 类型。

      现在,即使您将"No one" 作为name 传递,由于过滤器,Option 将评估为NonegetOrElse 将为您提供默认的"No one",而不是异常。

      【讨论】:

      • “param”的变量参数在我的要求中可以是字符串或整数,所以我想知道如何根据输入传递字符串或整数并获取字符串或整数作为返回类型我的程序。我的“参数”列表有字符串和整数类型。我想知道如何将混合数据类型传递给“参数”。 val Res2 = Hello("Vik", "rakesh", 1, "Jack", 2, "Vik", "vinccent", "ram", 4, "No one") ==> return "vinccent" val Res3 = Hello(5, "rakesh", 1, "Jack", 2, "Vik", "vinccent", "ram", 4, 5, "Five", "No one") ==> return "五"跨度>
      • 我已修改答案以解决您的评论。我很抱歉,我的第一个猜测是错误的。顺便说一句,您是否必须传递 only Int 或 String,并且应该在编译时进行检查?
      猜你喜欢
      • 2023-03-08
      • 2015-12-26
      • 1970-01-01
      • 2023-04-01
      • 2017-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多