我如何扩展Swift的数组<T>或T[]类型与自定义功能utils?

浏览Swift的API文档可以发现Array方法是T[]的扩展,例如:

extension T[] : ArrayType {
    //...
    init()

    var count: Int { get }

    var capacity: Int { get }

    var isEmpty: Bool { get }

    func copy() -> T[]
}

当复制和粘贴相同的源代码,并尝试任何变化,如:

extension T[] : ArrayType {
    func foo(){}
}

extension T[] {
    func foo(){}
}

它无法构建错误:

标称类型T[]不能扩展

使用完整的类型定义在使用未定义类型'T'时失败,即:

extension Array<T> {
    func foo(){}
}

当Array<T: Any>和Array<String>时也会失败。

奇怪的是,Swift让我扩展了一个无类型数组:

extension Array {
    func each(fn: (Any) -> ()) {
        for i in self {
            fn(i)
        }
    }
}

它让我调用:

[1,2,3].each(println)

但是我不能创建一个适当的泛型类型扩展,因为类型似乎在它流经方法时丢失了,例如试图用:

extension Array {
    func find<T>(fn: (T) -> Bool) -> T[] {
        var to = T[]()
        for x in self {
            let t = x as T
            if fn(t) {
                to += t
            }
        }
        return to
    }
}

但是编译器将它视为无类型的,它仍然允许调用扩展:

["A","B","C"].find { $0 > "A" }

当使用调试器进行步进时,则表示类型为Swift。字符串,但这是一个构建错误,试图访问它像一个字符串,而不首先将其转换为字符串,即:

["A","B","C"].find { ($0 as String).compare("A") > 0 }

有人知道创建类似内置扩展的类型化扩展方法的正确方法吗?


当前回答

如果你想了解扩展数组和其他类型的内置类的签出代码在这个github repo https://github.com/ankurp/Cent

从Xcode 6.1开始,扩展数组的语法如下所示

extension Array {
    func at(indexes: Int...) -> [Element] {
        ... // You code goes herer
    }
}

其他回答

扩展数组查找索引:

extension Array where Element: Equatable {
func findElementArrayIndex(findElement: String) -> Int {
    var indexValue: Int = 0
    var search = self.filter { findElement.isEmpty || "\($0)".contains(findElement)}
    //print("search: \(search)")
    for i in 0..<self.count {
        if self[i] == search[0] {
            indexValue = i
            break
        }
    }
    return indexValue
}

}

如果你想了解扩展数组和其他类型的内置类的签出代码在这个github repo https://github.com/ankurp/Cent

从Xcode 6.1开始,扩展数组的语法如下所示

extension Array {
    func at(indexes: Int...) -> [Element] {
        ... // You code goes herer
    }
}

对于用类扩展类型化数组,下面的方法适合我(Swift 2.2)。例如,对类型化数组排序:

class HighScoreEntry {
    let score:Int
}

extension Array where Element == HighScoreEntry {
    func sort() -> [HighScoreEntry] {
      return sort { $0.score < $1.score }
    }
}

尝试用struct或typealias这样做将会给出一个错误:

Type 'Element' constrained to a non-protocol type 'HighScoreEntry'

更新:

要使用非类扩展类型化数组,请使用以下方法:

typealias HighScoreEntry = (Int)

extension SequenceType where Generator.Element == HighScoreEntry {
    func sort() -> [HighScoreEntry] {
      return sort { $0 < $1 }
    }
}

在Swift 3中,一些类型被重命名:

extension Sequence where Iterator.Element == HighScoreEntry 
{
    // ...
}

使用Swift 2.2: 我在尝试从字符串数组中删除重复项时遇到了类似的问题。我能够在Array类上添加一个扩展,这正是我想要做的。

extension Array where Element: Hashable {
    /**
     * Remove duplicate elements from an array
     *
     * - returns: A new array without duplicates
     */
    func removeDuplicates() -> [Element] {
        var result: [Element] = []
        for value in self {
            if !result.contains(value) {
                result.append(value)
            }
        }
        return result
    }

    /**
     * Remove duplicate elements from an array
     */
    mutating func removeDuplicatesInPlace() {
        var result: [Element] = []
        for value in self {
            if !result.contains(value) {
                result.append(value)
            }
        }
        self = result
    }
}

将这两个方法添加到Array类中允许我调用数组上的两个方法中的一个,并成功地删除重复项。注意数组中的元素必须符合Hashable协议。现在我可以这样做:

 var dupes = ["one", "two", "two", "three"]
 let deDuped = dupes.removeDuplicates()
 dupes.removeDuplicatesInPlace()
 // result: ["one", "two", "three"]
import Foundation

extension Array {
    var randomItem: Element? {
        let idx = Int(arc4random_uniform(UInt32(self.count)))
        return self.isEmpty ? nil : self[idx]
    }
}