2013-04-30 82 views
0

可以說我想構造一個記錄列表,其中每個記錄包含一些x個字段。但是,編譯時不知道字段的數量和字段的類型。只有在運行時,我們都知道每個字段的字段數量和類型。因此,爲了表示這個列表,我使用了List [Array [Any]]。Scala類型安全和類型擦除相關問題

用戶應該能夠從該列表中找到某個字段的min(max)值的記錄。

這裏是一個高度簡化的示例代碼:

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) 

上面的代碼將不工作。斯卡拉給出了這樣的錯誤:

  • not enough arguments for method minBy: (implicit cmp: Ordering[Any])Array[Any]. Unspecified value parameter cmp.
  • No implicit Ordering defined for Any.

事實上,正如所料,斯卡拉隨時抱怨我把這個列表,如maxBy,sortWith,並和上上級的方法。

所以我修改了代碼,以這樣的:

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)) } 
    } 
} 

此代碼編譯並運行正常。不過,我覺得必須有比這更優雅的解決方案。另外,如果使用字符串類型的字段的索引調用min方法,則上述代碼將不起作用。

有沒有更好的方式來處理類型擦除和類型安全的情況下的數組[任何],其中數組存儲不同類型的元素,並且只有在運行時才知道其類型?

另外,是否有比List [Array [Any]]更好的數據類型來表示只有在運行時才知道其字段類型(和數量)的記錄列表?

謝謝。

+2

上述原因代碼不起作用是**不**類型擦除。 – 2013-04-30 18:58:03

回答

2

您的問題在於,您在隱式範圍內沒有正確的Ordering實例。一個不存在的原因是Ordering[Any]是不合情理的。即使我們有這樣一個實例,它的用途是什麼,比較StringInt意味着什麼?或者ObjectList?你可以組成一個訂單,但這將是無用的,因爲沒有辦法獲得有關Any類型的任何有趣的事情。有一些複雜的方法可以實現你想要的,但這似乎是設計問題的指示,你可能想重新考慮你的方法。

+0

請記住,類型在運行時是已知的,並且對於記錄中的每個位置,類型在列表中的任何位置都是相同的。換句話說,如果第一個字段在記錄#1中是Int類型,則第一個字段在所有其他記錄中將是Int類型。所以我們永遠不會比較String和Int。 – 2013-04-30 20:50:24