2013-07-04 119 views
1

有沒有辦法讓下面的活動更有效率?更有效的嵌套循環計算

+ (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訂單,點擊打開視圖控制器的按鈕會有明顯的延遲。

任何人都可以幫助提高這個效率嗎?我知道目前這很有趣嗎?

觀察

隨着@ 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]; 
    }]; 
} 

解析/ Unparsing的缺失使得該解決方案更快,另外,我設法削減了雙迴路和它上面的單迴路。

+0

也許我失去了一些東西,但是你爲什麼不BY子句添加命令,查詢從數據庫中提取? – bengoesboom

+0

@bengoesboom SQLite不支持日期時間字段,所以按日期字段排序會將其視爲字符串。在要求的日期格式中,可能存在不一致,因爲日期不是分層的(yyyy-mm-dd),而是美國的(mm-dd-yyyy)。 –

回答

2

最好的解決方案是以可排序格式在SQLITE中表示日期;自紀元以來的秒數是典型的。然後你可以使用ORDER BY作爲@bengoesboom建議。

如果你不能這樣做,那麼你可以將這兩個循環合併爲一個調用sortedArrayUsingComparator:,比較器進行轉換。

當然,這將會非常慢,因爲您會反覆解析日期。您確實需要將對象中的日期表示爲NSDates,可能是在從數據庫中獲取時進行轉換。

而且,當然,我希望你至少使用FMDB而不是原始SQLite API。另外,如果您不需要數據格式可移植性,請考慮使用核心數據。

+0

感謝您的幫助。我正在使用FMDB,是的 - 感謝您的幫助,我認爲如果我將數據屬性存儲爲NSDate而不是字符串,效率會更高,如您所建議的,我將進行此調整,然後研究改進循環!如果我可以刪除解析日期,那麼我可以有效地減少延遲。我會告訴你。 –

+0

感謝您的幫助@bbum,我更新了問題以包含我的解決方案,效率更高(更少線條!),再次感謝! –

+0

太棒了!樂於幫助。 – bbum

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