简单的Swift数组扩展

时间:2015-03-16 00:17:44

标签: 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)
}

}

我收到编译错误:“无法使用类型的参数列表调用insertionIndexOf(T,isOrderedBefore:(_,_) - &gt; _)”

奇怪的是,如果我改用:

    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)

2 个答案:

答案 0 :(得分: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)
    }
}

示例:

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

这些方法没有直接为struct Array定义,但对于某些方法 Array符合的协议,并提供必要的协议 方法

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

第二种方法变异 集合,这里是更具限制性的协议 <{1}}是必需的。

答案 1 :(得分:4)

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

extension Array where T: Comparable {

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

你最好的方法是让它成为一个功能:

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

或者创建一个HAS-A数组的新对象:

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