所以,我有一个排序NSArray
,其中包含NSString
个对象(从服务器下载),格式为:yyyy-MM-dd
。
它非常像这样:
NSArray <NSString *> *dates = @[@"2017-06-25",
@"2017-06-26",
@"2017-06-27",
@"2017-06-28",
@"2017-06-30",
@"2017-07-01",
@"2017-07-02",
@"2017-07-03"];
所以,今天是2017-06-29,它不在数组中。我如何得到下一个最近的一个?此示例为06-30
,但如果06-30
不存在,则可能是07-01 ...
更新
所以人们都在问我试图做些什么。所以就像这样(不是很有效,但是工作)
循环日期:
2.1将dateString
转换为date
2.2比较date
是否大于today
=&gt;如果是,则返回
如果在步骤#2中找不到,则返回日期数组中的最后一个对象。
实际代码:
NSDateFormatter *formatter = [NSDateFormatter new];
formatter.dateFormat = @"yyyy-MM-dd";
NSDate *today = [NSDate date];
NSUInteger index = [dates indexOfObject:[formatter stringFromDate:today]];
// Step 1
if (index == NSNotFound) {
// Step 2: Loop converted
NSInteger i = 0;
for (NSString *date in dates) {
// Step2.1: find the next nearest date's index
NSDate *convertedDate = [formmater dateFromString:date];
// Step2.2: Compare
if ([convertedDate intervalSinceDate:today] > 0) {
index = i;
break;
}
i++;
}
// Step 3: Still not found, index = last index
if (index == NSNotFound) index = i-1;
}
return dates[index];
这看起来不太好,因为我可能会重新加载日期数组。我可以有更好的解决方案吗?
答案 0 :(得分:3)
你的算法并不坏,虽然你的代码似乎没有实现它(没有排序?)。如果您想改进它,请考虑以下事项:
首先,在进行第一次扫描以检查完全匹配时可能没什么意义 - 这可能是通过无序数组进行线性搜索(由indexOfObject:
实现),如果失败,则必须再次扫描为了近距离比赛,只需同时进行。
第二,排序没有优势,最好是O(NlogN),因为线性搜索O(N)会找到你需要的答案。
这是一幅草图:
NSString
转换为NSDate
,并将其称为target
bestMatch
,NSString
设为nil
。将bestDelta
,NSTimeInterval
设置为最大可能值DBL_MAX
。迭代dates
数组:
3.1。将字符串日期转换为NSDate
,例如date
3.2。将delta
设置为date
和target
3.3。如果delta
为零,则您具有完全匹配,请将其返回
3.4。如果delta
优于bestDelta
,请更新bestDelta
和bestMatch
迭代后bestMatch
是最佳匹配,如果没有,则为nil
。
这是一次迭代,O(N),完全匹配的早期回报。
HTH
答案 1 :(得分:0)
所以你有一个NSString
这样的数组
// input
NSArray<NSString *> * words = @[@"2017-06-25",
@"2017-06-26",
@"2017-06-27",
@"2017-06-28",
@"2017-06-30",
@"2017-07-01",
@"2017-07-02",
@"2017-07-03"];
NSString
数组转换为NSDate
首先,您需要将每个输入字符串转换为NSDate
NSMutableArray<NSDate *> * dates = [NSMutableArray new];
NSDateFormatter * dateFormatter = [NSDateFormatter new];
dateFormatter.dateFormat = @"yyyy-MM-dd";
for (NSString * word in words) {
[dates addObject:[dateFormatter dateFromString:word]];
}
nearestDate
现在您可以找到最近的日期
NSDate * nearestDate = nil;
NSTimeInterval deltaForNearesttDate = 0;
NSDate * now = [NSDate new];
for (NSDate * date in dates) {
NSTimeInterval delta = fabs([date timeIntervalSinceDate:now]);
if (nearestDate == nil || (delta < deltaForNearesttDate)) {
deltaForNearesttDate = delta;
nearestDate = date;
}
}
结果是nearestDate
变量
NSLog(@"%@", nearestDate);
2017年6月28日星期三00:00:00
答案 2 :(得分:0)
请为您的问题找到最简单的解决方案。 根据排序顺序更新了解决方案!
我们可以使用NSPredicate Block来解决。
static NSDateFormatter* formatter = nil;
static NSDate* today = nil;
// return an NSDate for a string given in yyyy-MM-dd
- (NSDate *)dateFromString:(NSString *)string {
if (formatter == nil) {
formatter = [NSDateFormatter new];
formatter.dateFormat = @"yyyy-MM-dd";
}
return [formatter dateFromString:string];
}
// Helps to return today date.
-(NSDate*) getTodayDate {
if (today == nil) {
today = [NSDate date];
}
return today;
}
// Helps to find nearest date from Array using Predicate
-(NSString*)findNearestDate:(NSArray*)dateArray {
today = nil;
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSString *dateString, NSDictionary *bind){
// this is the important part, lets get things in NSDate form so we can use them.
NSDate *dob = [self dateFromString:dateString];
NSComparisonResult result = [[self getTodayDate] compare:dob];
if (result == NSOrderedSame || result == NSOrderedAscending) {
return true;
}
return false;
}];
// Apply the predicate block.
NSArray *futureDates = [dateArray filteredArrayUsingPredicate:predicate];
if ([futureDates count] > 0) {
// Sort the Array.
futureDates = [futureDates sortedArrayUsingSelector: @selector(compare:)];
return [futureDates objectAtIndex:0];
}
return nil;
}
NSArray <NSString *> *dates = @[@"2017-06-25",
@"2017-06-26",
@"2017-06-27",
@"2017-06-28",
@"2017-06-30",
@"2017-07-01",
@"2017-07-02",
@"2017-07-03"];
NSLog(@"Nearest Date: %@", [self findNearestDate:dates]);
答案:最近的日期:2017-06-30