我将NSDate传递给以下函数,并希望在数组中找到与传入值最接近的NSDate。
请注意,我不想知道数组是否包含这篇文章的确切日期: Find NSDate in sorted NSArray
我想知道数组中哪个日期与我的参考日期最接近。
我必须经常这样做。以下工作但速度很慢 - 我怎样才能加快速度?
// Get the XYZ data nearest to the passed time
- (eciXYZ)eciDataForTime:(NSDate*)time {
// Iterate our list and find the nearest time
float nearestTime = 86400; // Maximum size of dataset ( 2 days )
int index = 0; // Track the index
int smallestDifferenceIndex = index; // Track the index with the smallest index
NSDate *lastListDate; // Track the closest list date
for ( index = 0 ; index < [self.time count]-1 ; index++ ) {
NSDate *listDate = [self.time objectAtIndex:index]; // Get the date - Time is an NSMutableArray of NSDates
// NSTimeInterval is specified in seconds; it yields sub-millisecond precision over a range of 10,000 years.
NSTimeInterval timeDifferenceBetweenDates = [listDate timeIntervalSinceDate:time];
if ( timeDifferenceBetweenDates < nearestTime && timeDifferenceBetweenDates > 0 ) {
nearestTime = timeDifferenceBetweenDates; // Update the tracker
smallestDifferenceIndex = index; // Update the smallest difference tracker
lastListDate = listDate; // Capture the closest date match
//NSLog(@"Time: %f %@",timeDifferenceBetweenDates,listDate);
}
}
答案 0 :(得分:3)
修改:我错误地认为NSMutableOrderedSet
会自动维护订单。在过去,我可能已经使用了一个子类来实现这种效果。除非你想要设置语义,否则在NSArray上使用它没有任何好处。
保持集合排序是保持搜索速度快的好方法。如果可以的话,使用在添加数组时必须保持数组的排序,或者只创建一次数组然后你就可以对它进行排序。NSOrderedSet
或NSMutableOrderedSet
而不是数组对象,否则
此外,您可以使用NSFastEnumeration
更快地枚举任何集合(符合协议)。
示例:
// for an NSOrdered set or NSArray of NSDates
for (NSDate* date in self.times) {
// do something with date
// cleaner, shorter code too
}
因为您的收藏品经过排序,您现在可以知道最接近的日期,而无需迭代整个收藏品(大部分时间)。
// searching for date closest to Tuesday
[Sunday] <- start search here
[Monday] <- one day before
[Thursday] <- two days after, we now know that Monday is closest
[Friday] <- never have to visit
[Saturday] <- never have to visit
正如@davecom所指出的,您可以使用二进制搜索更快地搜索。通常,您可以使用CFArrayBSearchValues
或indexOfObject:inSortedRange:options:usingComparator:
上的NSArray
方法(假设数组已排序,请注意)并将NSBinarySearchingOptions
传递给options参数来实现此目的。在您的情况下,这将无法工作,因为您不知道您正在寻找的确切对象或值。你必须推出自己的二进制搜索算法。
如果这不足以达到您的目的,我们可能需要有关上下文的更多信息。使用C数组/ C ++列表/ NSPointerArray时间戳可能是最好的主意。我觉得你最大的减速是Objective-C开销,特别是对于日期。如果你不在任何地方使用这些作为实际日期对象,那么你肯定最好使用时间戳。