【发布时间】:2017-12-10 19:00:09
【问题描述】:
我有一个 Int, CustomType, OtherCustomType 元组数组。数组按元组的 Int 部分排序。
为了在正确的位置添加新元素,我编写了一个二进制搜索函数来获取插入点索引。
该函数返回一个新元组Int, Bool,其中 Bool 表示该元素是否已经存在,而 Int 是新元素第一次出现的索引,或者是第一个大于新元素。
该函数是通用编写的,它接受一个可比较类型的数组和一个相同类型的新元素作为参数,因此,很明显,我不能简单地传递我的元组数组。
一个简单的解决方案是重新组织我的数据,而不是将三个值作为元组存储在一个数组中,我可以使用三个单独的数组,每个数组仅三个值中的一个。然后我只将第一个数组传递给二分搜索函数,然后在找到的索引处对所有三个数组执行所需的操作。
但是有没有办法让我的数据组织为元组,并且只将每个元组的一个元素传递给函数,就像我们能够在比较中忽略元组的一部分,比如 if tuple == (_ ,23, _) ?
这里是一些示例代码:
func findInsertPoint <T: Comparable> (forElement: T, inArray: [T]) -> (Int, Bool) {
var low = 0
var high = inArray.count
if forElement > inArray[high-1] {
return (high, false)
}
while low < high {
let mid = (low+high)/2
if inArray[mid] >= forElement {
high = mid
} else {
low = mid+1
}
}
return(low,(inArray[low] == forElement))
}
一个 Ints 数组工作得非常好:
// index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
var testArray = [1,2,5,7,8,11,12,12,12,15,19,22,22,26,52,56]
findInsertPoint(forElement: x, inArray: testArray)
// x = 17 returns (10,false)
// x = 19 returns (10,true)
但我的实际数组看起来像这样:
var testArray = [(4,"Bee",2.5),(5,"dog",1.0),(8,"dog",43.13)]
我如何传递一个仅包含每个元组第一部分的数组,而无需在每个函数调用中昂贵地创建一个实际的新数组?
可能会调用该函数:
findInsertPoint(forElement: 7 in Array: testArray.0)
这将是完美的,但我知道这不起作用。
对于只接受单一类型数组的函数调用,是否有一种 Swift 方法可以暂时忽略元组或结构的成员?
如果不是,我知道我的两种可能性是:
- 坚持我的定制二进制搜索,而不是上面代码中的通用搜索。
- 将元组分成 3 个单独的数组。
【问题讨论】:
-
通常的方法是传递自定义比较函数,例如这里:stackoverflow.com/a/26679191/1187415,类似于现有的排序方法,如developer.apple.com/documentation/swift/array/2296815-sorted。
-
" 我可以使用 3 个单独的数组,每个数组只有 3 个值中的一个。"大多数肯定不会这样做。那就是疯狂。
-
你能给我们一些可编译的样本数据来解决这个问题吗?
-
在元组中存储数据非常麻烦。我只使用元组作为方法的返回值。而是创建一个类或结构。