在已排序的NSArray中查找NSDate

时间:2013-08-09 02:57:46

标签: objective-c nsarray

我有一个NSDate对象的排序数组。我想要做的是创建一个方法,该方法接受日期并返回YES或NO,具体取决于是否可以在日期数组中找到该日期。

NSArray *dateArray;

-(BOOL)arrayContainsDate(NSDate *)d {
  // return YES if d is found in dateArray
}

我知道如何逐个浏览数组的每个元素,但我需要更快的方法。

3 个答案:

答案 0 :(得分:4)

在确定一组对象中是否存在对象时,如果您正在为Mac OS开发,请考虑使用NSSet / NSMutableSet对象(或NSOrderedSet / NSMutableOrderedSet X 10.7或iOS 5.0并希望保留集合中元素的顺序)。 NSSet容器旨在实现高效查找。当一个对象具有合适的hash(大多数Foundation对象都这样做)时,查找实际上是O(1),这比二进制搜索更快。

NSSet *dateSet = [NSSet setWithArray:dateArray];

if ([dateSet containsObject:date1])
{
    // do something
}

请注意,每次构建集合而不是从数组中转换它是很重要的,否则您将失去任何性能优势。

有关详细信息,请参阅here


由于您想要检查指定日期而不考虑时间,因此您需要在添加到集合之前截断日期值。例如(选择更好的名称,这只是一个例子):

// potentially add as a category method to NSDate

- (NSDate *) dateByTruncatingTime
{
    NSDateComponents *components = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:aDate];
    return [[NSCalendar currentCalendar] dateFromComponents:components];
}

// ------------- somewhere else -------------

- (void) actionHappened
{
    [myMutableSet addObject:[[NSDate date] dateByTruncatingTime]];
}

- (BOOL) didActionHappenOnDate:(NSDate *) aDate
{
    return [myMutableSet containsObject:[aDate dateByTruncatingTime]];
}

答案 1 :(得分:1)

在对数组进行排序时,请使用binary search。首先将您的日期与数组的中间元素进行比较(使用compare:) - 如果相等,则找到它。如果它小于或大于那么重复考虑阵列的前半部分或后半部分。等

您可以使用两个索引来执行此操作 - 您正在考虑的范围的最小值和最大值。计算中间指数,进行比较,然后考虑的新范围是min,middle-1或middle + 1,max。

这个算法是O(log2 N) - 你不会做得更好。

代码留作练习!

HTH

答案 2 :(得分:1)

你可以使用哈希。

NSDictionary *dict = {[NSString stringWithFormat:@"%@",date1]:@"",[NSString stringWithFormat:@"%@",date2]:@""}

- (BOOL) containsDate:(NSDate*)_d
{
   return [dict valueForKey:[NSString stringWithFormat:@"%@",_d]] != nil;
}