2012-03-14 47 views
39

我有一個整數值的NSMutableDictionary,我想獲得一個按鍵排列,按各自的值升序排列。例如,用這本字典:獲取按其各自的值排序的NSDictionary鍵

mutableDict = { 
    "A" = 2, 
    "B" = 4, 
    "C" = 3, 
    "D" = 1, 
} 

我想結束與陣列["D", "A", "C", "B"]。當然,我的真實詞典遠遠大於四項。

+0

有幾十個元素,我想要一個新的數組按鍵,按照包含整數的鍵的升序值排序 – Eric 2012-03-14 19:37:55

+0

Josh,對於我所要做的,是的,他們都是整數。感謝大家的幫助! – Eric 2012-03-14 19:44:48

回答

62

NSDictionary方法keysSortedByValueUsingComparator:應該做的伎倆。

你只需要一個返回NSComparisonResult的方法來比較對象的值。

你的字典是

NSMutableDictionary * myDict; 

而且你的陣列是

NSArray *myArray; 

myArray = [myDict keysSortedByValueUsingComparator: ^(id obj1, id obj2) { 

    if ([obj1 integerValue] > [obj2 integerValue]) { 

      return (NSComparisonResult)NSOrderedDescending; 
    } 
    if ([obj1 integerValue] < [obj2 integerValue]) { 

      return (NSComparisonResult)NSOrderedAscending; 
    } 

    return (NSComparisonResult)NSOrderedSame; 
}]; 

只需使用NSNumber對象而不是數字常量。

順便說一句,這是取自: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Collections/Articles/Dictionaries.html

+4

理查德的建議比我的更優雅,因爲NSNumber已經有了一個合適的比較函數,但我的可能更一般。 – 2012-03-14 19:41:40

+1

在大多數情況下,這個解決方案可以正常工作,但我的答案是支持響應'-compare:' – 2012-03-14 19:47:42

+0

的其他類型的能力。這將返回密鑰列表,是否可以直接獲取字典,而不是有排序的鍵列表 – 2016-09-27 09:41:00

26

NSDictionary有這個叫做allKeys整潔的方法。

如果你想要排序陣列,keysSortedByValueUsingComparator:應該做的伎倆。

理查德的解決方案也適用,但使一些額外的電話,你不一定需要:

// Assuming myDictionary was previously populated with NSNumber values. 
NSArray *orderedKeys = [myDictionary keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2){ 
    return [obj1 compare:obj2]; 
}]; 
+0

我編輯了我的問題,我認爲這是暗示鑰匙必須按順序鍵值 – Eric 2012-03-14 19:30:11

+0

我在尋求排序幫助。 – Eric 2012-03-14 19:32:31

+0

'keysSortedByValueUsingComparator:'會做這種排序。 – 2012-03-14 19:34:30

14

這裏有一個解決方案:

NSDictionary *dictionary; // initialize dictionary 
NSArray *sorted = [[dictionary allKeys] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 
    return [[dictionary objectForKey:obj1] compare:[dictionary objectForKey:obj2]]; 
}]; 
+0

只適用於alphabates開頭的字符串,但是當有一個以數字10開頭的字符串時,第一個字符串以「A」開頭,第三個字符串以「A」開頭之間的聯繫 – ViruMax 2014-03-10 06:57:34

+0

檢查上面的答案,它更直觀和簡潔,儘管這是做同樣的事情。 – nemesis 2014-09-01 16:25:24

13

最簡單的辦法:

[dictionary keysSortedByValueUsingSelector:@selector(compare:)]

+1

如何編寫比較函數 – 2015-06-10 14:20:49

+0

請說明比較方法。 – Tuhin 2015-10-05 05:43:26

+0

對於現有的類型(例如NSString),該方法已經存在。對於您自己創建的任何內容,該方法應根據順序返回NSOrderedAscending,NSOrderedSame或NSOrderedDescending。有關詳細信息,請參閱「比較:選項:範圍:」的文檔。 – dgatwood 2016-10-07 22:12:39

2

在這裏我做了這樣的事情:

NSMutableArray * weekDays = [[NSMutableArray alloc] initWithObjects:@"Sunday",@"Monday",@"Tuesday",@"Wednesday",@"Thursday",@"Friday",@"Saturday", nil]; 
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 
NSMutableArray *dictArray = [[NSMutableArray alloc] init]; 

for(int i = 0; i < [weekDays count]; i++) 
{ 
    dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:i],@"WeekDay",[weekDays objectAtIndex:i],@"Name",nil]; 
    [dictArray addObject:dict]; 
} 
NSLog(@"Before Sorting : %@",dictArray); 

@try 
{ 
    //for using NSSortDescriptor 
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"WeekDay" ascending:YES]; 
    NSArray *descriptor = @[sortDescriptor]; 
    NSArray *sortedArray = [dictArray sortedArrayUsingDescriptors:descriptor]; 
    NSLog(@"After Sorting : %@",sortedArray); 

    //for using predicate 
    //here i want to sort the value against weekday but only for WeekDay<=5 
    int count=5; 
    NSPredicate *Predicate = [NSPredicate predicateWithFormat:@"WeekDay <=%d",count]; 
    NSArray *results = [dictArray filteredArrayUsingPredicate:Predicate]; 

    NSLog(@"After Sorting using predicate : %@",results); 
} 
@catch (NSException *exception) 
{ 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Sorting cant be done because of some error" message:[NSString stringWithFormat:@"%@",exception] delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil]; 
    [alert setTag:500]; 
    [alert show]; 
    [alert release]; 
}