【问题标题】:Objective-C Fastest Way to find Closest NSDate in NSArrayObjective-C 在 NSArray 中找到最近的 NSDate 的最快方法
【发布时间】:2013-12-20 10:03:58
【问题描述】:

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

【问题讨论】:

    标签: objective-c nsarray nsdate nstimeinterval


    【解决方案1】:

    编辑:我误以为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 所指出的,您可以使用二分搜索更快地进行搜索。通常,您可以使用CFArrayBSearchValuesNSArray 上的indexOfObject:inSortedRange:options:usingComparator: 方法来实现这一点(它假定数组已排序,所以要小心)并将NSBinarySearchingOptions 传递给options 参数。在您的情况下,这将不起作用,因为您不知道您正在寻找的确切对象或值。您将不得不推出自己的二进制搜索算法。


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

    【讨论】:

    • 如果不能有重复的日期,则使用一组有效。否则使用数组是可行的——只要在添加值时保持数组排序。
    • @rmaddy 没错,但我认为这不适用于这种情况。没有足够的信息知道是否有。更新答案以反映这一点,谢谢。
    • 甚至更快的是通过排序数组进行二进制搜索,而不是像上一个示例中那样顺序搜索。
    • 你必须保持一个可变有序集合的排序方式与你对可变数组的排序一样,所以我不确定你为什么推荐前者而不是后者。
    • OrderedSet 只是意味着它可以有顺序,但它不会自动为您排序元素
    猜你喜欢
    • 1970-01-01
    • 2021-10-28
    • 2019-07-07
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多