Reputation: 6091
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
var s1 = S()
var s2 = S()
var s3 = S()
var equality = [s1,s2,s3].allEqual()
Upvotes: 8
Views: 2543
Reputation: 1236
In the latest 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 {
...
}
}
Upvotes: 3
Reputation: 151
for say the specific type is S
extension CollectionType where Generator.Element == S {
}
Upvotes: 6
Reputation: 14973
I created an extension that works lazily for any SequenceType
whose Element
s are 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. 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:
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:
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
Upvotes: 1