swift - 跨步协议(protocol)

标签 swift

我正在尝试转换以下 Swift 2.3 代码:

//Example usage:
//(0 ..< 778).binarySearch { $0 < 145 } // 145
extension CollectionType where Index: RandomAccessIndexType {

    /// Finds such index N that predicate is true for all elements up to
    /// but not including the index N, and is false for all elements
    /// starting with index N.
    /// Behavior is undefined if there is no such N.
    func binarySearch(predicate: Generator.Element -> Bool)
        -> Index {
        var low = startIndex
        var high = endIndex
        while low != high {
            let mid = low.advancedBy(low.distanceTo(high) / 2)
            if predicate(self[mid]) {
                low = mid.advancedBy(1)
            } else {
                high = mid
            }
        }
        return low
    }
}

进入 Swift 3 如下:

//Example usage:
//(0 ..< 778).binarySearch { $0 < 145 } // 145
extension Collection where Index: Strideable {

    /// Finds such index N that predicate is true for all elements up to
    /// but not including the index N, and is false for all elements
    /// starting with index N.
    /// Behavior is undefined if there is no such N.
    func binarySearch(predicate: (Generator.Element) -> Bool)
        -> Index {
        var low = startIndex
        var high = endIndex
        while low != high {
            let mid = low.advanced(by: low.distance(to: high) / 2)
            if predicate(self[mid]) {
                low = mid.advanced(to: 1)
            } else {
                high = mid
            }
        }
        return low
    }
}

错误

Binary operator '/' cannot be applied to operands of type 'self.Index.Stride' and 'Int'

let mid = low.advanced(by: low.distance(to: high)/2)

处被抛出

有任何关于如何修复它的帮助吗?

最佳答案

在 Swift 3 中,“Collections move their index”,比较 A New Model for Collections and Indices关于 Swift 进化。特别是,您不会在索引上调用 advancedBy(), 但是在集合上使用 index() 方法来推进索引。

所以你的方法将在 Swift 3 中实现为

extension RandomAccessCollection {

    func binarySearch(predicate: (Iterator.Element) -> Bool) -> Index {
        var low = startIndex
        var high = endIndex
        while low != high {
            let mid = index(low, offsetBy: distance(from: low, to: high)/2)
            if predicate(self[mid]) {
                low = index(after: mid)
            } else {
                high = mid
            }
        }
        return low
    }
}

同样的方法也可以作为 更通用的 Collection 类型,但是——正如 Vadim Yelagin 正确评论的那样, 如果无法完成索引/偏移量计算,则效率非常低 常数时间。

关于swift - 跨步协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40226479/

相关文章:

swift - Swift 中 UITextfield 字符数限制

swift - 字符串的模式匹配

ios - 无法获取用户当前位置

ios - 全局更新导航栏按钮项目的颜色

ios - 快速拍照时前置摄像头自动变焦

ios - 转换后的 tableview 图像产生 "unexpectedly found nil while unwrapping optional"

ios - 单击表格 View 单元格上的按钮时如何获取 indexPath.row?

ios - 当 Parse 需要更新 UI 并在 viewDidLoad 中调用时,如何处理 Parse 调用主线程?

swift - 当按下开始按钮时,游戏分数会随着时间的推移而增加

ios - 无法使用解雇(动画: true,完成:nil)解雇邮件编辑器并且解雇ViewControllerAnimated不会作为选项出现