如何在Swift中为特定类型的数组进行扩展

时间:2015-08-05 20:36:38

标签: swift

因为我有:

struct S {
    var num = 0
}

我想实现一个函数allEqual()作为Array<S>的扩展,所以我可以做像

这样的事情
var s1 = S()
var s2 = S()
var s3 = S()
var equality = [s1,s2,s3].allEqual()

3 个答案:

答案 0 :(得分:3)

比如说具体的类型是S

extension CollectionType where Generator.Element == S {
}

CollectionType Protocol

答案 1 :(得分:1)

我为SequenceTypeElement的任何Equatable创建了一个懒惰的扩展程序。在Swift中,优良作法是使代码完全按照它可以工作的方式工作:为了能够得到所有元素是否相等,它必须是一系列相等的值。这是代码:

extension SequenceType where Generator.Element : Equatable {
    var allEqual : Bool {
        var gen = generate()           // Generate the sequence for the first element
        return gen.next().map { fst in // Get first element and map it (when existing)
            !contains { fst != $0 }    // To whether self doesn't contain any elements unequal to first
        } ?? true                      // When first is nil, return true
    }                                   
}

或者您也可以进行更多迭代(基本相同我认为更快?):

extension SequenceType where Generator.Element : Equatable {
    var allEqual : Bool {
        var gen = generate()
        let first = gen.next()
        return !contains { $0 != first }
    }
}

此外,您应该使您的结构符合Equatable协议,如下所示:

func ==(lhs: S, rhs: S) -> Bool {
    return lhs.x == rhs.x
}

因为every value type should be equatable显然在你的代码中完全有意义。

以下是一些测试代码:

[S(x: 3), S(x: 3), S(x: 3)].allEqual    // true
[S(x: 5), S(x: 3), S(x: 3)].allEqual    // false
[S(x: 5), S(x: 5)].allEqual             // true
[S(x: 0)].allEqual                      // true
[S]().allEqual                          // true

请注意,它是懒惰的,这意味着只要有一个不等于第一个元素的元素,它就会返回false,所以如果你有这样的东西:

let longList = [S(x: 5)] + [S](count: 100000, repeatedValue: S(x: 4))
    // [{x 5}, {x 4}, {x 4}, {x 4}, {x 4}, {x 4}, {x 4}, ...
longList.allEqual   // false

将返回第二个元素,因为已经存在相等性

编辑:我之前的功能不必要地复杂化了。新的还是懒得更短

答案 2 :(得分:0)

在最新的Swift 3.1中。您可以在具体类型扩展上执行相同类型的约束。所以在你的情况下,你可以这样做:

extension Array where Element == S {
    func allEqual() -> Bool {
        ...
    }
}