【问题标题】:Simple Swift Array Extension简单的 Swift 数组扩展
【发布时间】:2015-03-16 00:17:44
【问题描述】:

尝试扩展 Array 类型以使用二进制排序来按顺序插入元素。 这是我的游乐场代码:

  extension Array  {

      func insertionIndexOf(elem: T , isOrderedBefore: (T, T) -> Bool) -> Int {
       var lo = 0
       var hi = self.count - 1
       while lo <= hi {
        let mid = (lo + hi)/2
        if isOrderedBefore(self[mid], elem) {
            lo = mid + 1
        } else if isOrderedBefore(elem, self[mid]) {
            hi = mid - 1
        } else {
            return mid
        }
    }
        return 0 
 }


  mutating func insertOrdered(elem: T){
     let index = self.insertionIndexOf(elem, isOrderedBefore: { (a , b)     in return (a > b) } )
     return insert(elem, atIndex: index)
}

}

我得到一个编译器错误:“不能调用带有类型参数列表的insertionIndexOf (T, isOrderedBefore: (_, _) -> _)”

奇怪的是,如果我改用:

    mutating func insertOrdered(elem: T){
         let index = self.insertionIndexOf(elem, isOrderedBefore: { (a , b) in return false } )
         return insert(elem, atIndex: index)
        }

编译器平静下来,但数组插入不会被排序,:(当然。 请问有什么想法吗??谢谢。

(使用 Xcode 6.3 beta 2 - Swift 1.2)

【问题讨论】:

标签: arrays swift swift-playground


【解决方案1】:

从 Swift 2 开始,这可以通过协议扩展方法来实现:

extension CollectionType where Generator.Element : Comparable, Index == Int {

    func insertionIndexOf(elem: Generator.Element) -> Int {
        var lo = 0
        var hi = self.count - 1
        while lo <= hi {
            let mid = (lo + hi)/2
            if self[mid] < elem {
                lo = mid + 1
            } else if elem < self[mid] {
                hi = mid - 1
            } else {
                return mid // found at position mid
            }
        }
        return lo // not found, would be inserted at position lo
    }
}

extension RangeReplaceableCollectionType where Generator.Element : Comparable, Index == Int {

    mutating func insertOrdered(elem: Generator.Element) {
        let index = self.insertionIndexOf(elem)
        self.insert(elem, atIndex: index)
    }
}

例子:

var ar = [1, 3, 5, 7]
ar.insertOrdered(6)
print(ar) // [1, 3, 5, 6, 7]

这些方法不是直接为struct Array定义的,而是为一些 Array 符合的协议,并提供了必要的 方法。

对于第一种方法,即CollectionType,因为 提供(读取)下标访问,以及集合元素 类型必须是Comparable

第二种方法变异 集合,这里是更严格的协议 RangeReplaceableCollectionType 为必填项。

【讨论】:

    【解决方案2】:

    您正在尝试评估a &gt; b,但T 可能不是Comparable。今天不可能写出这样的扩展。你想说的是:

    extension Array where T: Comparable {
    

    但目前这在 Swift 中是不可能的。编译器团队已经表示这是一个优先事项,但我们不知道它什么时候会涉及到 Swift。

    你最好的方法是让它成为一个函数:

    func insertOrdered<T: Comparable>(inout xs: [T], x: T)
    

    或者创建一个具有数组的新对象:

    struct OrderedArray<T: Comparable> : ... {
        var values: [T]
        func insertionIndexOf(elem: T , isOrderedBefore: (T, T) -> Bool) -> Int
        mutating func inserOrdered(elem: T)
        ...
    }
    

    【讨论】:

    • 感谢一百万个罗伯!我会试试你的建议
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多