在 Swift 中使用 where 子句扩展数组类型
Extend array types using where clause in Swift
我想使用 Accelerate 框架来扩展 [Float] 和 [Double],但每个都需要不同的实现。
我尝试了显而易见的方法:
extension Array<Float> {
}
并得到这个错误:
"Constrained extension must be declared on the unspecialised generic
type 'Array' with constraints specified by a 'where' clause"
是否可以通过这种方式扩展 Swift 2 中的泛型类型?
我的代码现在可以正常工作了。下面是一个使用 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
}
}
怎么样
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
的任何其他类型。如果您需要访问数组的特定索引,请将 SequenceType
更改为 CollectionType
,因为您不能对序列执行此操作。
所以我没有正确阅读问题。 FloatingPointType
是Double、Float和CGFloat实现的现有协议,所以
是的。我昨天才这样做,向 SequenceType 添加一个函数,其中元素必须是 Equatable
。这是将元素限制为Float
的修改
您需要使用 where 子句。这是我下面的功能。
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]]
注意,我无法将此用于数组,但 SequenceType 更通用。
如果您只想扩展特定的 Array
您必须为每种类型使用一个协议:
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
}
如果只想扩展特定类型的数组。您应该扩展 _ArrayType 协议。
extension _ArrayType where Generator.Element == Int {
func doSomething() {
...
}
}
如果您扩展 Array
,您只能确保您的元素符合其他协议。即:
extension Array where Element: Equatable {
func doSomething() {
...
}
}
更新:
用Swift3.1https://github.com/apple/swift/blob/master/CHANGELOG.md
extension Array where Element == Int {
func doSomething() {
...
}
}
Swift 3 人来救援!!
extension Collection where Iterator.Element == Int {
// `Collection` can be `Sequence`, etc
}
Swift 3 在 Xcode 8.2
只需要扩展Sequence 协议并提供一个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([=10=])!
}
}
}
let arrayOfStrings = someString.toArrayOfElements()
print(arrayOfStrings)
let arrayOfInts = arrayOfStrings.toInt()
print(arrayOfInts)
这对我有用。我正在使用 Swift 5
.
extension Array where Iterator.Element == Float {
}
这就是我使用 Swift 5
时的效果:
extension Array where ArrayLiteralElement == Float {
}
我想使用 Accelerate 框架来扩展 [Float] 和 [Double],但每个都需要不同的实现。
我尝试了显而易见的方法:
extension Array<Float> {
}
并得到这个错误:
"Constrained extension must be declared on the unspecialised generic type 'Array' with constraints specified by a 'where' clause"
是否可以通过这种方式扩展 Swift 2 中的泛型类型?
我的代码现在可以正常工作了。下面是一个使用 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
}
}
怎么样
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
的任何其他类型。如果您需要访问数组的特定索引,请将 SequenceType
更改为 CollectionType
,因为您不能对序列执行此操作。
所以我没有正确阅读问题。 FloatingPointType
是Double、Float和CGFloat实现的现有协议,所以
是的。我昨天才这样做,向 SequenceType 添加一个函数,其中元素必须是 Equatable
。这是将元素限制为Float
您需要使用 where 子句。这是我下面的功能。
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]]
注意,我无法将此用于数组,但 SequenceType 更通用。
如果您只想扩展特定的 Array
您必须为每种类型使用一个协议:
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
}
如果只想扩展特定类型的数组。您应该扩展 _ArrayType 协议。
extension _ArrayType where Generator.Element == Int {
func doSomething() {
...
}
}
如果您扩展 Array
,您只能确保您的元素符合其他协议。即:
extension Array where Element: Equatable {
func doSomething() {
...
}
}
更新: 用Swift3.1https://github.com/apple/swift/blob/master/CHANGELOG.md
extension Array where Element == Int {
func doSomething() {
...
}
}
Swift 3 人来救援!!
extension Collection where Iterator.Element == Int {
// `Collection` can be `Sequence`, etc
}
Swift 3 在 Xcode 8.2
只需要扩展Sequence 协议并提供一个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([=10=])!
}
}
}
let arrayOfStrings = someString.toArrayOfElements()
print(arrayOfStrings)
let arrayOfInts = arrayOfStrings.toInt()
print(arrayOfInts)
这对我有用。我正在使用 Swift 5
.
extension Array where Iterator.Element == Float {
}
这就是我使用 Swift 5
时的效果:
extension Array where ArrayLiteralElement == Float {
}