我的代码基本上是这样的:
func arrayHalvesEqual(data:[UInt8]) -> Bool {
let midPoint = data.count / 2
for i in 0..<midPoint {
let b = data[i]
let b2 = data[i + midPoint]
if b != b2 {
return false
}
}
return true
}
这样可以正常工作,但有时我想传入Arrays,有时则传入ArraySlice。我以为我将其更改为使用泛型和CollectionType
协议,该协议转换如下:
func arrayHalvesEqual<ByteArray : CollectionType where ByteArray.Generator.Element == UInt8>(data:ByteArray) -> Bool {
let midPoint = data.count / 2
for i in 0..<midPoint {
let b = data[i]
let b2 = data[i + midPoint]
if b != b2 {
return false
}
}
return true
}
但是,我收到以下编译器错误:
error: binary operator '..<' cannot be applied to operands of type 'Int' and 'ByteArray.Index.Distance'
for i in 0..<midPoint {
我可以将for循环切换到for i in data.indices
进行编译,但是我不能再将它除以2来获取midPoint,因为data.indices返回抽象CollectionType.Index
而/ 2是一个Int。
在Swift中可以做这样的事吗?我可以在抽象协议索引类型和一些可以进行数学运算的实际类型之间架桥吗?
PS:我已经看过并发现了使用indices
和enumerate
迭代整个集合的其他示例,但我显然只想迭代一半的集合,这需要某种排序除以2
由于
答案 0 :(得分:1)
您可以将方法限制为已编制索引的集合
Int
:
func arrayHalvesEqual<ByteArray : CollectionType where ByteArray.Index == Int, ByteArray.Generator.Element == UInt8>
(data:ByteArray) -> Bool { ... }
这包括Array
和ArraySlice
。
如果您使用indices.startIndex
而不是0
作为初始索引
那么将索引类型限制为IntegerType
就足够了。
此外,数据类型UInt8
可以替换为通用Equatable
,
并且整个方法缩短为
func arrayHalvesEqual<ByteArray : CollectionType where ByteArray.Index : IntegerType, ByteArray.SubSequence.Generator.Element : Equatable>
(data:ByteArray) -> Bool {
let midPoint = (data.indices.endIndex - data.indices.startIndex)/2
let firstHalf = data[data.indices.startIndex ..< midPoint]
let secondHalf = data[midPoint ..< data.indices.endIndex]
return !zip(firstHalf, secondHalf).contains { $0 != $1 }
}