【问题标题】:Sort the array to get nearest dates to a given date对数组进行排序以获取最接近给定日期的日期
【发布时间】:2015-05-09 04:42:39
【问题描述】:

该数组包含以下字典。

NSArray *availableSlots = @[@{@"start" : <NSDate obj> , @"end" : <NSDate obj>},
                        @{@"start" : <NSDate obj> , @"end" : <NSDate obj>},
                        @{@"start" : <NSDate obj> , @"end" : <NSDate obj>},
                        @{@"start" : <NSDate obj> , @"end" : <NSDate obj>} ...];

我想获得与所选日期最近的开始日期和结束日期。

这里是这个解决方案的 js Pseudocode 函数。我想把它转换成Objective C。

function sortByProximityToPoint(a, b) {
        if (a.proximToPoint === undefined) {
            if (pointInTime.diff(a.start, 'minute') >= 0 &&
                pointInTime.diff(a.end, 'minute') <= 0) {
                a.proximToPoint = 0;
            } else if (pointInTime.diff(a.end, 'minute') > 0) {
                a.proximToPoint = Math.abs(pointInTime.diff(a.end, 'minute'));
            } else {
                a.proximToPoint = Math.abs(pointInTime.diff(a.start, 'minute'));
            }
        }

        if (b.proximToPoint === undefined) {
            if (pointInTime.diff(b.start, 'minute') >= 0 &&
                pointInTime.diff(b.end, 'minute') <= 0) {
                b.proximToPoint = 0;
            } else if (pointInTime.diff(b.end, 'minute') > 0) {
                b.proximToPoint = Math.abs(pointInTime.diff(b.end, 'minute'));
            } else {
                b.proximToPoint = Math.abs(pointInTime.diff(b.start, 'minute'));
            }
        }

        if (a.proximToPoint < b.proximToPoint) {
            return -1;
        }
        if (a.proximToPoint > b.proximToPoint) {
            return 1;
        }

        return 0;
    }

    availableSlots.sort(sortByProximityToPoint);

【问题讨论】:

  • NSDate提供了比较和差异的方法,(Objective-)C中有abs函数,你到底有什么问题?
  • 我想获取pointInTime(选定日期)最近的可用插槽。
  • 明白了,你甚至有一些代码可以做到这一点。转换到 Objective-C 时,你在哪里卡住了? (您可以编辑问题以显示这一点。)
  • 问题:开始/结束的一对值可以与另一个相交吗?您是否需要找到恰好在开始/结束对值范围内的开始/结束对?与日期相比,开始/结束对值是否可以在过去或需要在将来?你真的需要排序,还是只找到最接近的几个值?
  • @Larne - 好问题,但是由于提供了比较功能(只是在伪代码中)并且它是合理的,所以我们不需要问。 (任务似乎类似于在给定客户请求的现场时间的情况下找到最佳的可用预约时间,并且无论有单个或多个预约流[例如多个医生/理发师/等],它都有效)

标签: ios objective-c sorting nsarray nsdate


【解决方案1】:

只是即使我能看懂JavaScript伪代码,没有cmets/explanation,也需要更多时间,有时用文字和例子来解释更清楚。特别是对于可能遇到相同问题的人,快速查看这是否适合他/这里的问题。

所以你不明白算法的作用,想要用英文解释而不是伪代码?

该函数是一个典型的比较函数,它返回三个值之一(-10+1)以指示其两个参数的顺序。您可以在许多语言中看到这种约定,Objective-C使用符号名称(NSOrderedAscending 等)而不是数字(但实际上它们只是相同的三个数字)。

前两个部分产生一个适合于比较每个提供的参数间隔的数值。使用S 表示间隔的开始时间,E 表示结束时间,并使用P 与这些部分进行比较的时间点处理三种情况:

Time ->      P          S           E

P在开始时间之前:返回时差S - P。这是 P 与区间的“距离”。

Time ->      S          P           E

P在区间内:返回0

Time ->      S          E           P

P在结束时间之后:返回时差P - E。这是 P 与区间的“距离”。

现在算法有两个数字要比较,较小的意思是“更好”,这意味着排在前面。因此它比较两个数字并返回指示顺序的适当值。

在 Objective-C 中,您将使用块而不是函数,将其直接传递给 NSArray 的适当排序方法。日期时间比较和差异函数来自NSDate

虽然您可以实现与“proxim”值(伪代码中的 undefined 内容)等效的 Javascript 缓存,但您应该将其保留到并且如果您认为有必要。只需使用本地(块)变量。

还请注意,绝对值函数的使用是不必要的 - 考虑一下。

HTH

【讨论】:

  • 是一个很好的解释CRD。我终于设法想出了 Obj-c 代码。希望我的回答也能对某人有所帮助
【解决方案2】:
// sort them
NSArray *sortedArray = [availableSlots sortedArrayUsingComparator:^NSComparisonResult(NSMutableDictionary* a, NSMutableDictionary* b) {

    if (a[@"proximToPoint"] == [NSNull null]) {
        if ([(NSDate *)a[@"start"] compare:time] != NSOrderedDescending && [(NSDate *)a[@"end"] compare:time] != NSOrderedAscending) {
            [a setObject:@0 forKey:@"proximToPoint"];
        } else if ([(NSDate *)a[@"end"] compare:time] == NSOrderedAscending){
            [a setObject:@(abs([(NSDate *)a[@"end"] compare:time])) forKey:@"proximToPoint"];
        } else {
            [a setObject:@(abs([(NSDate *)a[@"start"] compare:time])) forKey:@"proximToPoint"];
        }
    }

    if (b[@"proximToPoint"] == [NSNull null]) {
        if ([(NSDate *)b[@"start"] compare:time] != NSOrderedDescending && [(NSDate *)b[@"end"] compare:time] != NSOrderedAscending) {
            [b setObject:@0 forKey:@"proximToPoint"];
        } else if ([(NSDate *)b[@"end"] compare:time] == NSOrderedAscending){
            [b setObject:@(abs([(NSDate *)b[@"end"] compare:time])) forKey:@"proximToPoint"];
        } else {
            [b setObject:@(abs([(NSDate *)b[@"start"] compare:time])) forKey:@"proximToPoint"];
        }
    }

    if (a[@"proximToPoint"] > b[@"proximToPoint"]) {
        return (NSComparisonResult)NSOrderedDescending;
    }

    if (a[@"proximToPoint"] < b[@"proximToPoint"]) {
        return (NSComparisonResult)NSOrderedAscending;
    }

    return (NSComparisonResult)NSOrderedSame;
}];

【讨论】:

  • 对不起,但这个答案没有实现算法,它也不起作用。 proximToPoint 值始终是 0(指向插槽内)或 1(指向插槽外)。再次阅读我对算法的解释。您还模拟了 Javascript 动态添加属性的能力,要求所有要排序的元素都是可变字典并且在排序开始之前有一个值为 [NSNull null] 的键 proximToPoint。您的答案不包括执行此操作的代码;你不需要做这个缓存,但如果你这样做了,你能想出更好的方法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
  • 2014-12-23
相关资源
最近更新 更多