Find NSDate in sorted NSArray

风格不统一 提交于 2019-12-24 20:37:56

问题


I have a sorted array of NSDate objects. What I'd like to do is create a method that takes in a date and returns YES or NO depending on whether that date can be found in the date array.

NSArray *dateArray;

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

I know how to do this by going through each element of the array one by one, but I need a quicker way.


回答1:


When determining whether an object exists in a set of objects, consider using an NSSet/NSMutableSet object (or NSOrderedSet/NSMutableOrderedSet if you are developing for Mac OS X 10.7 or iOS 5.0 and want to retain the order of elements in the set). An NSSet container is designed for efficient lookups. When an object has a decent hash (which most Foundation objects do), the lookup is effectively O(1), which is faster than a binary search.

NSSet *dateSet = [NSSet setWithArray:dateArray];

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

Note that it is important to construct the set once rather than converting it from an array each time, or else you'll lose any performance benefit.

For more information, see here.


Since you are wanting to check for specified dates regardless of time, you need to truncate the date values before adding them to the set. For example (pick better names, this is only an example):

// 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]];
}



回答2:


you can use hash.

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

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



回答3:


As your array is sorted use binary search. Start by comparing your date with the middle element of the array (use compare:) - if it is equal you found it. If it is less or greater then repeat considering just the first half or second half of the array. Etc.

You do this by using two indices - min and max of the range you are considering. Calculate the middle index, do the comparison and then your new range to consider is min, middle-1 or middle+1, max.

This algorithm is O(log2 N) - you won't do better.

Code is left as an exercise!

HTH



来源:https://stackoverflow.com/questions/18139459/find-nsdate-in-sorted-nsarray

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!