I have an array of tuples of Int, CustomType, OtherCustomType
. The array is sorted by the Int part of the tuples.
To add new elements at the correct position I wrote a binary search function to get the insertion point index.
The function returns a new tuple of Int, Bool
, where Bool tells if the element is already present, and Int is either the index of the first occurrence of the new element, or the index of the first element which is larger than the new element.
The function is written genericly, and takes an array of a comparable type and a new element of the same type as arguments, so, obviously, I cannot simply pass my array of tuples.
A simple solution would be to re-organize my data so, instead of storing three values as tuples in one array, I could use three separate arrays, each of only one of the three values. I would then pass only the first array to the binary search function and then perform the desired action on all three arrays at the found index.
But is there a way to keep my data organized as tuples and pass only one element of each tuple to the function, like we are able to ignore parts of a tuple in comparisons like if tuple == (_ ,23, _)
?
Here is some sample code:
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))
}
An array of Ints works perfectly fine:
// 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)
But my actual array looks something like this:
var testArray = [(4,"Bee",2.5),(5,"dog",1.0),(8,"dog",43.13)]
How do I pass an array of only the first part of each tuple, but without the expensive creation of an actual new array each function call?
A possibility would be to call the function:
findInsertPoint(forElement: 7 in Array: testArray.0)
which would be perfect, but I know this doesn't work.
Is there a Swift way to temporarily ignore members of a tuple or a struct for a function call that only accepts arrays of a single type?
If not, I know my two possibilities are:
- stick to my taylored binary search, not the generic one from the code above.
- divide the tuple into 3 separate arrays.