2012-06-20 42 views
1

我已經讀過一些關於清單和擦除 - 避免技術,讓斯卡拉做像「新陣列[數組[T]]」,但我有點難以忍受這一個....我的數組的Scala參數化假設一個字符串?

我有一種方法,像電子數據表一樣排列一堆行。例如設想一個2D陣列是這樣的:

11, 5, 4 
8, 3, 7 
2, 1, 4 

我寫總結了該陣列的列和吐出一維數組,例如[21,9,15]

欲泛化的方法它超越了Ints(比如Doubles或Floats),當我添加一個參數和清單時,我得到一個編譯錯誤。

下面的代碼

def sumGrid[T](grid: Array[Array[T]])(implicit m: ClassManifest[T]): Array[T] = { 

    val sum = new Array[T](grid(0).size) 

    for(i <- 0 until grid.size) { 
    for(j <- 0 until grid(0).size) { 
     sum(j) = sum(j) + grid(i)(j) 
    } 
    } 
    sum 
} 

這裏的編譯錯誤:

[ERROR] ...scala/euler/GridOperations.scala:126: error: type mismatch; 
[INFO] found : T 
[INFO] required: String 
[INFO]   sum(j) = sum(j) + grid(i)(j) 
[INFO]        ^
[ERROR] one error found 

這是怎麼回事?爲什麼字符串「需要」?

+3

注意,在這種情況下,你可以通過編寫'高清sumGrid迴避問題[T:數字(格:數組[​​數組[T])= grid.transpose.map(_總和) '。 –

回答

6

因爲您使用總是爲字符串定義的+運算符。任何類型都可以轉換爲字符串(總是定義toString),因此它適用於任何類型的T

但是您可以在T上添加一些約束,以確保它對應於算術運算。例如,你可以使用implicits獲得Numeric對象定義T型加法:

def sumGrid[T](grid: Array[Array[T]]) 
(implicit m: ClassManifest[T], num: Numeric[T]): Array[T] = { 

    val sum = new Array[T](grid(0).size) 

    for(i <- 0 until grid.size) { 
    for(j <- 0 until grid(0).size) { 
     sum(j) = num.plus(sum(j), grid(i)(j)) 
    } 
    } 
    sum 
} 
+0

謝謝,範例!那就是訣竅。 – user311121

0

您處理的Array一部分,但T不具有說它有一個+方法的任何約束。因此,Scala認爲您正在添加字符串 - 當您將其添加到另一個String時,它會自動將任何類型轉換爲String。所以它會自動將sum(j)轉換爲String,現在預計grid(i)(j)是另一個String,此時它放棄並失敗。

你可以用類似於ClassManifest的東西來處理關於T的事情。在這裏:

// I'm using the "context bound" notation, to make the declaration shorter and 
// more obvious on what I'm saying about T 
def sumGrid[T : ClassManifest : Numeric](grid: Array[Array[T]]): Array[T] = { 
    // the following line, plus the Numeric bound, makes T usable as a number 
    import scala.math.Numeric.Implicits._ 

    val sum = new Array[T](grid(0).size) 

    for(i <- 0 until grid.size) { 
    for(j <- 0 until grid(0).size) { 
     sum(j) = sum(j) + grid(i)(j) 
    } 
    } 
    sum 
} 
相關問題