简单的 Swift 数组扩展
Posted
技术标签:
【中文标题】简单的 Swift 数组扩展【英文标题】:Simple Swift Array Extension 【发布时间】: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)
【问题讨论】:
那段代码看起来很眼熟***.com/a/26679191/1187415 :) – 注意最后的return 0
应该是return lo
。
@MartinR 是的 :) 我使用您的示例进行二分搜索,以便为我的问题添加上下文。我一直在玩扩展名。抱歉,刚刚忘记添加指向您的代码的链接。希望没有伤害。
@MartinR ***.com/questions/29107928/…
【参考方案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 > 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 数组扩展的主要内容,如果未能解决你的问题,请参考以下文章
Swift 中的 Array 扩展以使用 NSPropertyListReadOptions 从 plist 中读取数组