更有效的嵌套循环计算

时间:2013-07-04 16:02:05

标签: objective-c sorting nsmutablearray nested-loops

有没有办法让下面的活动更有效率。

+ (NSMutableArray *)sortArrayOfOrdersByDate:(NSMutableArray *)array{

    //create an array of the dates from the Order class
    NSMutableArray *dates = [[NSMutableArray alloc] init];
    for (Order *order in array)
        [dates addObject:[Utility parseDateFromString:order.date format:@"MM-dd-yyyy HH:mm"]];

    //algorithm to sort the array of dates
    NSArray *datesSorted = [dates sortedArrayUsingComparator: 
        ^(id obj1, id obj2) {
             return [obj2 compare:obj1];
        }];

    //match and build a complete, sorted array of orders
    NSMutableArray *ordersSorted = [[NSMutableArray alloc] init];
    for (NSDate *theDate in datesSorted)
        for (Order *order in array)
            if ([[Utility parseStringFromDate:theDate format:@"MM-dd-yyyy HH:mm"] isEqualToString:order.date])
                [ordersSorted addObject:order];

    return ordersSorted;
}

我将解释发生了什么,我有一个名为Order的类,它从数据库中提取 由于数据库是SQLite,它不支持日期时间字段,因此我无法轻松地从查询中按日期排序,这就是我编写此函数的方法。

订单有一个属性'date',它只是一串文字。
为此,我正在使用此值的日期解析版本创建一个NSDates数组。

我对日期进行排序,然后尝试通过比较每个日期的字符串解析版本以及存储在order.date中的内容来创建一个新数组

我的测试数据库中有大约80个订单,点击打开viewcontroller的按钮会有明显的延迟。

任何人都可以帮助提高效率吗,我知道目前它很漂亮吗?

观察

使用@ bbum的建议,我将order.date属性解析并存储为NSDate,当它出自数据库时,然后使用简单的sortedArrayUsingComparator:调用,可以轻松比较order.date属性。

请参阅下面的解决方案:

+ (NSArray *)sortArrayOfOrdersByDate:(NSMutableArray *)array{
    return [array sortedArrayUsingComparator:^(id obj1, id obj2) {
        return [((Order *)obj2).date compare:((Order *)obj1).date];
    }];
}

缺少解析/解析使得这个解决方案更快,同时,我设法减少了双循环和它上面的单循环。

2 个答案:

答案 0 :(得分:2)

最好的解决方案是以可排序的格式在SQLITE中表示日期;因为纪元是典型的秒数。然后你可以使用ORDER BY作为@bengoesboom建议。

如果你不能这样做,那么你可以将这两个循环折叠成一次调用sortedArrayUsingComparator:,比较器进行转换。

当然,这会非常慢,因为你会反复解析日期。您确实需要将对象中的日期表示为NSDates,可能是从数据库中提取时进行转换。

当然,我希望你至少使用像FMDB这样的东西而不是原始的SQLite API。同样,如果您不需要数据格式可移植性,请考虑使用Core Data。

答案 1 :(得分:1)

两个选项:

一个。如果您控制数据库中记录的格式并希望将日期存储为字符串(而不是数字),则将它们存储为字符串格式yyyy-MM-dd HH:mm。这些日期仍然是人类可读的,也可以正确排序为字符串。您现在可以使用SQL查询来提取已排序的记录。

B中。如果您无法控制上述格式,则可以改进算法。

您可以考虑直接对订单数组进行排序,但如果这样做,您将多次将字符串转换为日期,并且成本可能会很高。

另一种选择是创建一个{date,order}对的数组,按日期对该数组进行排序,该对的第一个元素,然后是您的订单,该对的第二个元素的顺序正确。然后,您可以解压缩对并生成一系列已排序的订单。要做到这一点,你需要为对等定义一个类。

第三种选择,也许加速/轻松的最佳组合是用日期数组和日期字典替换上面的对 - >命令。字典基于散列 - O(1) - 因此速度很快。这样做的大纲是(即代码未经测试):

+ (NSMutableArray *)sortArrayOfOrdersByDate:(NSMutableArray *)array
{

    //create an array of the dates from the Order class
    NSMutableArray *dates = [NSMutableArray new];
    NSMutableDictionary *dateToOrder = [NSMutableDictionary new];

    for (Order *order in array)
    {
        NSDate *orderDate = [Utility parseDateFromString:order.date format:@"MM-dd-yyyy HH:mm"];
        [dates addObject:orderdate];
        [dateToOrder addObject:order forKey:orderDate];
    }

    //algorithm to sort the array of dates
    NSArray *datesSorted = [dates sortedArrayUsingComparator: 
        ^(id obj1, id obj2) {
             return [obj2 compare:obj1];
        }];

    // O(n) extraction of sorted orders
    // notFoundMarker unused as dates only contains keys in the dictionary
    NSArray *ordersSorted = [dateToOrder objectsForKeys:dates notFoundMarker:[NSNull null]];

    return ordersSorted;
}