I have an array with a bunch of NSNumber
s. From an UISlider
I get a certain value when the user stops dragging it. I would like to get the closes number from the array.
So for instance, if the user drags the UISlider
to 13
, and the NSArray
contains the NSNumbers
with 10
and 15
; I want to get 15
from the array.
Example of array:
NSArray *values = [NSArray arrayWithObjects:[NSNumber numberWithInt:15],
[NSNumber numberWithInt:20],
[NSNumber numberWithInt:30],
[NSNumber numberWithInt:45],
[NSNumber numberWithInt:60],
[NSNumber numberWithInt:90],
[NSNumber numberWithInt:110], nil];
How do I get the correct number from the array?
In your post, the array is sorted. If it's always sorted, you can use binary search. NSArray
has a convenient method for that:
CGFloat targetNumber = mySlider.value;
NSUInteger index = [values indexOfObject:@(targetNumber)
inSortedRange:NSMakeRange(0, values.count)
options:NSBinarySearchingFirstEqual | NSBinarySearchingInsertionIndex
usingComparator:^(id a, id b) {
return [a compare:b];
}];
Now there are four possibilities:
values
is larger than targetNumber
: index
is zero.values
is smaller than targetNumber
: index
is values.count
.values
contains targetNumber
: index
is the index of targetNumber
in values
.index
is the index of the smallest element of values
that is greater than targetNumber
.I've cleverly listed the cases in the order we'll handle them. Here's case 1:
if (index == 0) {
return [values[0] floatValue];
}
Here's case 2:
if (index == values.count) {
return [[values lastObject] floatValue];
}
We can handle cases 3 and 4 together:
CGFloat leftDifference = targetNumber - [values[index - 1] floatValue];
CGFloat rightDifference = [values[index] floatValue] - targetNumber;
if (leftDifference < rightDifference) {
--index;
}
return [values[index] floatValue];