简体   繁体   English

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

[英]How can I make a extension for array of specific type in Swift

for say I have: 比方说我有:

struct S {
    var num = 0
}

I wanna implement a function allEqual() as extension for Array<S> , so I could do thing like 我想实现一个函数allEqual()作为Array<S>扩展,所以我可以这样做

var s1 = S()
var s2 = S()
var s3 = S()
var equality = [s1,s2,s3].allEqual()

for say the specific type is S 比如说具体的类型是S.

extension CollectionType where Generator.Element == S {
}

CollectionType Protocol CollectionType协议

I created an extension that works lazily for any SequenceType whose Element s are Equatable . 我创建了一个懒洋洋的作品对于任何一个扩展SequenceType ,其Element s为Equatable In Swift, it is good practice to make your code work on exactly what it can work on: To be able to get whether all elements are equal it has to be a sequence of equatable values. 在Swift中,优良作法是使代码完全按照它可以工作的方式工作:为了能够得到所有元素是否相等,它必须是一系列相等的值。 Here is the code: 这是代码:

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
    }                                   
}

Or you can also do it more iterative (which is basically the same I think is faster? ): 或者你也可以做更多的迭代(基本上 我认为更快? ):

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

Also you should make your struct conform to the Equatable protocol like this: 您还应该使您的结构符合Equatable协议,如下所示:

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

because every value type should be equatable and obviously it makes total sense in your code to do this. 因为每个值类型都应该是等同的 ,显然在代码中完全有意义。

Here is some test code: 这是一些测试代码:

[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

Note that it is lazy, which means that it will return false as soon as there is an element which isn't equal to the first one, so if you have something like this: 请注意,它是惰性的,这意味着只要有一个不等于第一个元素的元素,它就会返回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

will return at the second element, because there is an equality already 将返回第二个元素,因为已经存在相等性

EDIT: My previous function was unnecessarily complicated. 编辑:我以前的功能不必要地复杂。 The new one is still lazy just shorter 新的仍然懒得更短

In the latest Swift 3.1. 在最新的Swift 3.1中。 You can do same-type constraints on the concrete type extension . 您可以对具体类型扩展执行相同类型的约束 So in your case, you can do: 所以在你的情况下,你可以这样做:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM