假设我想构建一个记录列表,其中每条记录由一些 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]] 更好的数据类型来表示仅在运行时才知道字段类型(和编号)的记录列表?
谢谢你。