在Swift中使用where子句扩展数组types
我想使用Accelerate框架来扩展[Float]和[Double],但是每个都需要不同的实现。
我试过很明显的:
extension Array<Float> { }
并得到这个错误:
“约束扩展必须在非专用genericstypes'Array'上声明,其约束由'where'子句指定”
以这种方式扩展Swift 2中的genericstypes是否可行?
我已经得到了代码正常工作。 以下是一个使用Accelerate框架显示总和的示例。
extension _ArrayType where Generator.Element == Float { func quickSum() -> Float { var result: Float = 0 if var x = self as? [Float] { vDSP_sve(&x, 1, &result, vDSP_Length(x.count)) } return result } } extension _ArrayType where Generator.Element == Double { func quickSum() -> Double { var result: Double = 0 if var x = self as? [Double] { vDSP_sveD(&x, 1, &result, vDSP_Length(x.count)) } return result } }
如果你想扩展只有特定types的数组。 你应该扩展_ArrayType协议。
extension _ArrayType where Generator.Element == Int { func doSomething() { ... } }
如果你扩展Array
你只能确保你的元素符合其他协议。 即:
extension Array where Element: Equatable { func doSomething() { ... } }
更新:使用Swift 3.1 https://github.com/apple/swift/blob/master/CHANGELOG.md
extension Array where Element == Int { func doSomething() { ... } }
斯威夫特3救援!
extension Collection where Iterator.Element == Int { // `Collection` can be `Sequence`, etc }
怎么样
extension CollectionType where Generator.Element == Double { }
或者如果你想多一点:
protocol ArithmeticType { func +(lhs: Self, rhs: Self) -> Self func -(lhs: Self, rhs: Self) -> Self func *(lhs: Self, rhs: Self) -> Self func /(lhs: Self, rhs: Self) -> Self } extension Double : ArithmeticType {} extension Float : ArithmeticType {} extension SequenceType where Generator.Element : protocol<FloatLiteralConvertible, ArithmeticType> { var sum : Generator.Element { return reduce(0.0, combine: +) } var product : Generator.Element { return reduce(1.0, combine: *) } } stride(from: 1.0, through: 10.0, by: 1.0).sum // 55 [1.5, 2.0, 3.5, 4.0, 5.5].product // 231
使用Double
和Float
或符合协议ArithmeticType
和FloatLiteralConvertible
任何其他types。 如果您需要访问数组的特定索引,请将SequenceType
更改为CollectionType
因为您无法使用序列执行此操作。
所以我没有正确地阅读这个问题。 FloatingPointType
是由Double,Float和CGFloat实现的现有协议
是。 我只是在昨天才添加一个函数给SequenceType,其中的元素必须是Equatable
。 这是一个将元素限制为Float
的修改
你需要使用一个where子句。 这是我的function如下。
public extension SequenceType where Self.Generator.Element: FloatingPointType { public func splitAt(separator: Generator.Element) -> [[Generator.Element]] { var ret: [[Generator.Element]] = [] var thisPart: [Generator.Element] = [] for element in self { if element == separator { ret.append(thisPart) thisPart = [] } else { thisPart.append(element) } } ret.append(thisPart) return ret } } [Float(1), Float(2), Float(3), Float(4)].splitAt(Float(2)) // returns [[1],[3, 4]] [Double(1), Double(2), Double(3), Double(4)].splitAt(Double(3)) // returns [[1, 2],[4]]
NB我不能使这个工作的数组,但SequenceType是更一般的反正。
如果你只想扩展一个特定的Array
你必须为每个types使用一个协议:
protocol DoubleValue { var value: Double { get } } extension Double: DoubleValue { var value: Double { return self } } extension Array where Element: DoubleValue { // use the value property } // the same for Float protocol FloatValue { var value: Float { get } } extension Float: FloatValue { var value: Float { return self } } extension Array where Element: FloatValue { // use the value property }
Swift 3在Xcode 8.2上
只需要扩展序列协议,并提供一个where语句。
let someString = "1, 2, 3, 4, 5, 6, 7, 8" extension String { func toArrayOfElements() -> [String] { return self.components(separatedBy: ", ") } } extension Sequence where Iterator.Element == String { func toInt() -> [Int] { return self.map { Int($0)! } } } let arrayOfStrings = someString.toArrayOfElements() print(arrayOfStrings) let arrayOfInts = arrayOfStrings.toInt() print(arrayOfInts)