繁体   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