简单 Swift 数组扩展

Simple Swift Array Extension

正在尝试扩展 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)
}

}

我收到一个编译器错误:"cannot invoke insertionIndexOf with argument list of type ( 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 测试版 2 - Swift 1.2)

您正在尝试评估 a > 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)
    ...
}

从 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 为必填项。