简单的Swift数组扩展

Ble*_*pes 5 arrays swift swift-playground

尝试扩展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)
}
Run Code Online (Sandbox Code Playgroud)

}

我得到一个编译器错误:"无法使用类型的参数列表调用insertionIndexOf(T,isOrderedBefore:(_,_) - > _)"

奇怪的是,如果我改用:

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

编译器平静下来,但数组插入不会被命令,:(当然.请任何想法?谢谢.

(使用Xcode 6.3 beta 2 - Swift 1.2)

Mar*_*n R 5

从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)
    }
}
Run Code Online (Sandbox Code Playgroud)

例:

var ar = [1, 3, 5, 7]
ar.insertOrdered(6)
print(ar) // [1, 3, 5, 6, 7]
Run Code Online (Sandbox Code Playgroud)

这些方法不是struct Array直接定义的,而是针对某些Array符合的协议,并提供必要的方法.

对于第一种方法,那是CollectionType因为它提供了(读取)下标访问,并且需要集合元素类型Comparable.

第二种方法改变了集合,这里RangeReplaceableCollectionType需要更严格的协议 .


Rob*_*ier 4

您正在尝试评估a > b,但T可能不会Comparable。今天不可能编写这样的扩展。您希望能够说的是:

extension Array where T: Comparable {
Run Code Online (Sandbox Code Playgroud)

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

最好的方法是使其成为一个函数:

func insertOrdered<T: Comparable>(inout xs: [T], x: T)
Run Code Online (Sandbox Code Playgroud)

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

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