在字符串数组中查找最近的日期
Find nearest date in string array
所以,我有一个包含 NSString
对象(从服务器下载)的排序 NSArray
,格式为: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...
更新
所以人们问我我试图做什么。所以是这样的(不是很有效,但是有效)
- 查找今天是否在数组中(如果是,return)
循环日期:
2.1 将dateString
转换为date
2.2 比较 date
是否大于 today
=> return 如果是
如果在步骤#2 中未找到,return 日期数组中的最后一个对象。
实际代码:
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];
这看起来不太好,因为我可能会重新加载日期数组。我可以有更好的解决方案吗?
1。输入
所以你有一个 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"];
2。将 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]];
}
3。找到 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;
}
}
4。结论
结果进入nearestDate
变量所以
NSLog(@"%@", nearestDate);
Wed Jun 28 00:00:00 2017
您的算法还不错,尽管您的代码似乎没有实现它(不是吗?)。如果您想改进它,请考虑:
首先,进行第一次扫描以检查精确匹配可能没有什么意义 - 这可能是通过无序数组的线性搜索(由 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
为零,则表示完全匹配,return 则
3.4。如果 delta
优于 bestDelta
,请更新 bestDelta
和 bestMatch
迭代后 bestMatch
是最佳匹配,如果没有匹配则 nil
。
这是单次迭代,O(N),早 return 精确匹配。
HTH
请为您的问题找到最简单的解决方案。 更新了基于排序的解决方案!
我们可以使用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
所以,我有一个包含 NSString
对象(从服务器下载)的排序 NSArray
,格式为: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...
更新
所以人们问我我试图做什么。所以是这样的(不是很有效,但是有效)
- 查找今天是否在数组中(如果是,return)
循环日期:
2.1 将
dateString
转换为date
2.2 比较
date
是否大于today
=> return 如果是如果在步骤#2 中未找到,return 日期数组中的最后一个对象。
实际代码:
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];
这看起来不太好,因为我可能会重新加载日期数组。我可以有更好的解决方案吗?
1。输入
所以你有一个 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"];
2。将 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]];
}
3。找到 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;
}
}
4。结论
结果进入nearestDate
变量所以
NSLog(@"%@", nearestDate);
Wed Jun 28 00:00:00 2017
您的算法还不错,尽管您的代码似乎没有实现它(不是吗?)。如果您想改进它,请考虑:
首先,进行第一次扫描以检查精确匹配可能没有什么意义 - 这可能是通过无序数组的线性搜索(由 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
为零,则表示完全匹配,return 则3.4。如果
delta
优于bestDelta
,请更新bestDelta
和bestMatch
迭代后
bestMatch
是最佳匹配,如果没有匹配则nil
。
这是单次迭代,O(N),早 return 精确匹配。
HTH
请为您的问题找到最简单的解决方案。 更新了基于排序的解决方案!
我们可以使用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