簡體   English   中英

Swift 3:如何檢查通用數組的類型

[英]Swift 3: How to check the type of a generic array

我聲明一個通用數組

  fileprivate var array: [T?]

我有一個方法average(),如果'T'是Int或Float,它將計算平均值; 否則返回0

  public   func average() -> Float {
    var mean = 0
    if T is Int or Float {
     for   index in (0..<array.count-1){
         mean = mean+array[index]
        }
        mean = mean/array.count
     }
     return mean;
  }

問題:如何檢查數組是否持有Int / Float( 如果上面的代碼中T為Int或Float則為

這是用於協議的工具。 對於您的問題有用的協議是FloatingPoint處理浮點類型(如Float )和Integer處理有符號整數類型(如Int )。 它們的實現略有不同,因此最好分別編寫每個。 這樣做將確保此方法僅適用於適當的T類型(而不是所有可能的類型,在這些情況下僅返回0)。

extension MyStruct where T: FloatingPoint {
    func average() -> T {
        let sum = array.flatMap{$0}.reduce(0, +)
        let count = T(array.count)
        return sum.divided(by: count)
    }
}

extension MyStruct where T: Integer {
    func average() -> Float {
        let sum = array.flatMap{$0}.reduce(0, +)
        let count = array.count
        return Float(sum.toIntMax()) / Float(count.toIntMax())
    }
}

編輯:下面對Caleb的評論進行了更多介紹,您可能會認為將整數轉換為浮點數以生成平均值是可以的。 但是,如果不仔細考慮范圍,通常這是不安全的。 例如,考慮[Int.min, Int.max]的平均值。 那是[-9223372036854775808, 9223372036854775807] 平均值應為-0.5,這就是我上面的示例所返回的結果。 但是,如果將所有內容都轉換為浮點數以求和,則會得到0,因為Float無法精確表示Int.max 我見過有人在實時代碼中咬人,當他們不記得很大的浮點數時, x == x+1

Float(Int.max) == Float(Int.max - 1) // true

您將需要遍歷數組,並使用“ if let”解開數組中值的類型。 如果它們是整數,則以一種方式處理它們;如果它們是浮點數,則以另一種方式處理它們。

//在遍歷數組時,請檢查您的元素以查看它們是浮點數還是整數。

if let stringArray = T as? Int {
    // obj is a string array. Do something with stringArray
}
else {
    // obj is not a string array
}

您可以通過以下方式使用Swift 3中引入的type方法:

let type = type(of: array)
print("type: \(type)") // if T is String, you will see Array<Optional<String>> here

這是一個高級描述:

... inside a loop which allows indexing
if let ex = array[index] as? Int {
    your code
    continue // go around the loop again, you're all done here
}
if let ex = array[index] as? Float {
    // other code
    continue  // go around the loop again, you're all done here
}
// if you got here it isn't either of them
// code to handle that
... end of inside the loop

如果還不夠清楚,我可以進一步解釋。

這可能是最簡單的方法:

var average: Float {
    let total = array.reduce(0.0) { (runningTotal, item) -> Float in

        if let itemAsFloat = item as? Float {
            return runningTotal + itemAsFloat
        }
        else if let itemAsInt = item as? Int {
            return runningTotal + Float(itemAsInt)
        }
        else {
            return runningTotal
        }
    }
    return total / Float(array.count)
}

顯然,如果您希望它可以是一個函數,則可能需要對其進行調整,具體取決於您希望使用它的方式。

*請注意,有可能在T數組中同時包含IntFloat 例如,如果TAny

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM