【问题标题】:Scala: Best Way to Avoid Multiple time doing same operation in different Match-caseScala:避免在不同匹配情况下多次执行相同操作的最佳方法
【发布时间】:2025-12-27 23:10:15
【问题描述】:

我想在表的一行中找到所有值的最小值(可能有空值,列可能是不同的类型——Int、Long、Double、Boolean)。

函数的返回类型取决于输入列,如果都是 Int 则返回类型应该是 Int。如果混合不同类型,则加倍,等等。

我知道 returnType 是什么。

方法如下:

 def findMin(args: List[Any]): Any =

一种可能的解决方案是:

returnType match {
  case IntType =>
     minValInt = Int.Min
     for(args){
        check for not null 
        for(arg <- args) {
          temp: Int  = arg match {
             case x: Int => x
             case x: Boolean => convert to Int              
          }
        minValInt = min(minValInt, temp)
        return minValInt

  case LongType =>
     minValLong = Long.Min
     for(args){
       check for not null -> minValLong = min(minValLong, arg) (some restrictions while using the arg value directly)
     }
     return minValLong

  case DoubleType =>
     minValDouble = Double.Min
     for(arg <- args){
       check for not null 
       temp: Double = arg match {
          case x: Int => convert to double 
          case x: Long => convert to double (some restrictions while converting)
          case x: Double => x
          case x: Boolean => convert to double
       }
       minValDouble = min(minValDouble, temp)
     }
     return minValDouble
}

这可以在单个匹配情况下完成还是更好的“更整洁”?

【问题讨论】:

  • 你不能让一个函数根据它的参数返回不同的类型,所以它会返回 Any 所以你会在某个地方进行强制转换。都有点乱。用例是什么?您将返回的最小值用于什么用途?
  • @ArchetypalPaul 当然可以。它被称为泛型 ;) (或任何东西在 scala 中的花哨名称)。
  • @Dima - 当然你不能。泛型是关于在编译时基于参数 TYPES 的类型计算。这个问题是关于在运行时根据动态识别的值类型计算返回类型。
  • @Det,我只是说上一条评论中的“您不能让单个函数根据其参数返回不同类型的函数”的说法是错误的。我们同意吗?您的陈述也好不到哪里去 :) 首先,您误读了这个问题:OP 说,他 知道 返回类型应该是什么。其次,看你怎么错了,简单地考虑这个函数:def identity[T](x: T) = x它的返回类型是不同的,取决于参数。这只是一个最简单的例子,当然,您可以使用 manifests 和implicits 做更多更奇特的事情。
  • 因为“Any”是 Scala 中所有类型的超集。因此,根据参数返回不同的类型是可行的。

标签: scala


【解决方案1】:

大概是这样的吧?

list.flatMap(x => Option(x)).minBy { 
   case n: Number => n.doubleValue
   case true => 1.0
   case false => 0.0
}(Ordering.Double)

【讨论】:

    【解决方案2】:

    除了我对用例缺乏想象力之外,您已经在您的问题中将函数类型定义为 List [Any] -> Any。

    因此,您实际上没有告诉编译器会发生什么,并失去了拥有静态类型系统的优势。

    请注意,使用静态类型的函数式编程是关于定义输入域并在编译时将其映射到输出域。 因此,返回 Int 的函数与返回 Long 的函数或返回 Double 的函数不同。因此,要么它们是不同的函数,要么将输出域定义为所有可能返回类型的公共超类型,从而在途中丢失特定信息。

    关于显示的代码,返回类型似乎是 Int、Long、Double 中的任何一种,具体取决于返回最小值所需的最大精度。

    由于 Int 适合 Long 并且都适合 Double,为什么不将 Double 声明为保证的最大精度返回类型?

    因此该函数将是 List[Any] -> Double 类型,从而使程序的其余部分在编译时特定于类型安全?

    【讨论】:

    • 在这种情况下会错过精度说:9223372036854775807,9223372036854775800,9223372036854775801 最小值:9223372036854775800 但如果是双倍:92235872036857 甚至会通过
    • 确切的用例是最后还必须显示返回值的类型。所以,如果我想找到 min(long, long),那么我希望结果是 long。首先,我将所有内容都转换为双精度,然后发现上面的测试用例即使在给出错误的预期值后也通过了。
    最近更新 更多