【发布时间】:2015-08-05 20:36:38
【问题描述】:
说我有:
struct S {
var num = 0
}
我想实现一个函数 allEqual() 作为Array<S> 的扩展,所以我可以这样做
var s1 = S()
var s2 = S()
var s3 = S()
var equality = [s1,s2,s3].allEqual()
【问题讨论】:
标签: swift
说我有:
struct S {
var num = 0
}
我想实现一个函数 allEqual() 作为Array<S> 的扩展,所以我可以这样做
var s1 = S()
var s2 = S()
var s3 = S()
var equality = [s1,s2,s3].allEqual()
【问题讨论】:
标签: swift
【讨论】:
extension Array where Element == Int cf. stackoverflow.com/a/34672403/1354835
在最新的 Swift 3.1 中。您可以对具体类型扩展进行相同类型的约束。所以在你的情况下,你可以这样做:
extension Array where Element == S {
func allEqual() -> Bool {
...
}
}
【讨论】:
我创建了一个扩展,它可以懒惰地为Elements 为Equatable 的任何SequenceType 工作。在 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
将在第二个元素处返回,因为已经存在相等性
编辑:我之前的功能过于复杂。新的还是懒惰的,只是更短了
【讨论】: