0

假设我想构建一个记录列表,其中每条记录由一些 x 个字段组成。但是,字段的数量和字段的类型在编译时是未知的。只有在运行时,我们才知道字段的数量和每个字段的类型。所以为了表示这个列表,我使用了一个 List[Array[Any]]。

用户应该能够从此列表中找到某个字段的最小值(最大值)的记录。

这是一个高度简化的示例代码:

class Data(val colValues: List[Array[Any]]) {
  def min(i: Int): Array[Any] = {
    colValues.minBy { _(i) }
  }
}

用户应该能够以这种方式使用它:

val rawData = List(Array("a", 20, "z", "m", 3.0), Array("b", 10, "y", "f", 4.0), Array("c", 40, "z", "m", 2.0))
val d =  new Data(rawData)
val m1 = d.min(1)
val m2 = d.min(4)

上面的代码将不起作用。Scala给出了这个错误:

  • 方法 minBy 的参数不足:(隐式 cmp:Ordering[Any])Array[Any]。未指定值参数 cmp。
  • 没有为 Any 定义隐式排序。

事实上,正如预期的那样,每当我调用此列表中的高阶方法(如 maxBy、sortWith 和 sum)时,Scala 都会抱怨。

所以我将代码修改为:

class Data(val colValues: List[Array[Any]]) {
  def withType(x: Any) = x match {
          case i: Int => i
          case l: Long => l
          case f: Float => f
          case d: Double => d
  }

  def min(i: Int): Array[Any] = {
    colValues.minBy { x:Array[Any] => withType(x(i)) }
  }
}

此代码按预期编译和运行。但是,我觉得一定有比这更优雅的解决方案。另外,如果使用 String 类型字段的索引调用 min 方法,则上述代码将不起作用。

在 Array[Any] 的情况下,是否有更好的方法来处理类型擦除和类型安全,其中数组存储不同类型的元素并且其类型仅在运行时才知道?

此外,是否有比 List[Array[Any]] 更好的数据类型来表示仅在运行时才知道字段类型(和编号)的记录列表?

谢谢你。

4

1 回答 1

2

Ordering您的问题是您在隐式范围内没有正确的实例。一个不存在的原因是没有Ordering[Any]意义的。即使我们有这样一个实例,它的用途是什么,比较 aString和是什么意思Int?还是一个Object和一个List?您可以进行排序,但这将毫无用处,因为没有办法获得关于类型的任何有趣的东西Any。有一些复杂的方法可以实现您想要的,但这似乎表明存在设计问题,您可能需要尝试重新考虑您的方法。

于 2013-04-30T19:35:32.807 回答