1

我的代码基本上是这样的:

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
}

这很好用,但有时我想传入数组,有时我想传入 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 i in data.indices进行编译的 for 循环,但是我不能再将它除以 2 来获得 midPoint,因为 data.indices 返回抽象CollectionType.Index而 / 2 是一个 Int。

可以在 Swift 中做这样的事情吗?我可以在抽象协议索引类型和一些我可以做数学运算的真实类型之间架起桥梁吗?

indicesPS:我已经看到并找到了其他使用and迭代整个集合的示例enumerate,但我明确地只想迭代一半以上的集合,这需要某种除以 2

谢谢

4

1 回答 1

1

您可以将该方法限制为由以下索引的集合Int

func arrayHalvesEqual<ByteArray : CollectionType where ByteArray.Index == Int, ByteArray.Generator.Element == UInt8>
    (data:ByteArray) -> Bool { ... }

这涵盖了ArrayArraySlice

如果您使用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 }
}
于 2016-02-18T02:27:24.553 回答