Objective-C在NSArray中找到最近的NSDate的最快方法

时间:2013-12-04 03:59:47

标签: objective-c nsarray nsdate nstimeinterval

我将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);
        }
    }

1 个答案:

答案 0 :(得分:3)

修改:我错误地认为NSMutableOrderedSet会自动维护订单。在过去,我可能已经使用了一个子类来实现这种效果。除非你想要设置语义,否则在NSArray上使用它没有任何好处。

保持集合排序是保持搜索速度快的好方法。如果可以的话,使用NSOrderedSetNSMutableOrderedSet而不是数组对象,否则在添加数组时必须保持数组的排序,或者只创建一次数组然后你就可以对它进行排序。

此外,您可以使用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所指出的,您可以使用二进制搜索更快地搜索。通常,您可以使用CFArrayBSearchValuesindexOfObject:inSortedRange:options:usingComparator:上的NSArray方法(假设数组已排序,请注意)并将NSBinarySearchingOptions传递给options参数来实现此目的。在您的情况下,这将无法工作,因为您不知道您正在寻找的确切对象或值。你必须推出自己的二进制搜索算法。


如果这不足以达到您的目的,我们可能需要有关上下文的更多信息。使用C数组/ C ++列表/ NSPointerArray时间戳可能是最好的主意。我觉得你最大的减速是Objective-C开销,特别是对于日期。如果你不在任何地方使用这些作为实际日期对象,那么你肯定最好使用时间戳。