【问题标题】:getting minimum and maximum value in List[Option[Int or Long or Float]]在 List[Option[Int or Long or Float]] 中获取最小值和最大值
【发布时间】:2015-05-12 14:50:13
【问题描述】:

我正在尝试获取有序数字列表中的最小值和最大值。 使用特定类型时没有问题:

private def minMaxValue (valuesList: List[Option[Int]], min: Boolean): Option[Int] = 
  valuesList.flatten match {
  case Nil => None
  case xs => Some(if (min) xs.min else xs.max)
}

但是当我找不到将其更改为也接受 Long 和 Float 的方法时,我尝试了:

private def minMaxValue (valuesList: List[Option[Any]], min: Boolean): Option[Int] = 
  valuesList.flatten match {
  case Nil => None
  case xs: List[Int] => Some(if (min) xs.min else xs.max)
  case xs: List[Long] => Some(if (min) xs.min else xs.max)
}

但它不起作用,我收到此警告

  • 类型模式 List[Int](List[Int] 的基础)中的非变量类型参数 Int 未选中,因为它被 擦除

在 scala 中解决此问题的最佳方法是什么?

【问题讨论】:

    标签: scala


    【解决方案1】:

    我会这样做:

    def minMaxValue[T <% Ordered[T]](valuesList: List[Option[T]], min: Boolean): Option[T] = 
      valuesList.flatten match {
        case Nil => None
        case xs => Some(if (min) xs.min else xs.max)
      }
    

    这将创建一个带有类型参数T 的泛型函​​数。您必须声明 T 是有序类型,这样编译器才能证明 Ts 的集合具有 minmax 方法。

    它适用于整数和双精度:

    scala> minMaxValue(List(Option(1), None, Option(3)), false)
    res7: Option[Int] = Some(3)
    
    scala> minMaxValue(List(Option(1.0), None, Option(3.0)), false)
    res8: Option[Double] = Some(3.0)
    
    scala> minMaxValue(List(Option(1.0), None, Option(3.0)), true)
    res9: Option[Double] = Some(1.0)
    

    JVM 中类型擦除的问题是类型参数仅在编译时可用,但在运行时不可用。在我的解决方案中,编译器看到T 类型,并且可以使用该信息进行类型检查和生成适用于您正在使用的T 特定值的函数。在您的代码中,您需要在运行时判断某事物是 List[Int] 还是 List[Long],但到那时该信息已被删除。

    【讨论】:

    • 注意视图边界已被弃用,您应该使用上下文边界,并且使用Ordering 而不是Ordered 更通用:def minMaxValue[T : Ordering]
    • @Kolmar,事实上,说“你应该使用上下文边界而不是视图边界”是不正确的——毕竟,上下文边界不是视图边界的直接替代。正确的方法是将视图边界扩展为隐式函数参数(例如,在这种情况下添加 (implicit ev: T =&gt; Ordered[T]))。也就是说,我确实同意在大多数情况下,特别是上下文边界和一般的类型类模式更好。
    • @VladimirMatveev 但是在任何具体情况下,用上下文边界直接替换视图边界都不是问题:jatinpuri.com/2014/03/replace-view-bounds 通常你可以定义trait As[M] { type View[T] = T =&gt; M },然后代替@987654338 @你有def foo[T : As[Int]#View]。只是有点冗长。
    【解决方案2】:

    我会将List[Option[Int]] 转换为List[Int] 以便能够使用maxmin 方法。

    val listOpt = List(Some(3), None, Some(7))
    
    val listValues = listOpt.collect{
      case Some(x) => x
    }
    
    listValues.max
    listValues.min
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多