尝试扩展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)
答案 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)
...
}