2012-03-14 4 views
39

Tôi có một giá trị số nguyên là NSMutableDictionary và tôi muốn lấy một dãy các khóa, được sắp xếp tăng dần theo giá trị tương ứng. Ví dụ: với từ điển này:Nhận các khóa NSDictionary được sắp xếp theo các giá trị tương ứng

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

Tôi muốn kết thúc với mảng ["D", "A", "C", "B"]. Từ điển thực sự của tôi lớn hơn nhiều so với chỉ bốn mục, tất nhiên.

+0

Có hàng chục phần tử, tôi muốn một mảng các phím mới được sắp xếp theo giá trị tăng dần của các khóa có chứa số nguyên – Eric

+0

Josh, cho những gì tôi đang cố gắng làm, có tất cả chúng đều là số nguyên. Cảm ơn sự giúp đỡ của mọi người! – Eric

Trả lời

62

Phương thức NSDictionary Phương pháp keysSortedByValueUsingComparator: nên thực hiện thủ thuật.

Bạn chỉ cần một phương thức trả về NSComparisonResult so sánh giá trị của đối tượng.

từ điển của bạn là

NSMutableDictionary * myDict; 

Và mảng của bạn là

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

Chỉ cần sử dụng NSNumber đối tượng thay vì hằng số.

BTW, đây được lấy từ: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Collections/Articles/Dictionaries.html

+4

Đề xuất của Richard là tao nhã hơn tôi bởi vì NSNumber đã đi kèm với một hàm so sánh phù hợp nhưng tôi có lẽ là tổng quát hơn. –

+1

Trong hầu hết các trường hợp, giải pháp này sẽ hoạt động tốt, nhưng câu trả lời của tôi là khả năng hỗ trợ các kiểu khác đáp ứng với '-compare:' –

+0

Điều này sẽ trả về danh sách khóa, có cách nào có thể lấy từ điển trực tiếp, thay vì có danh sách các khóa được sắp xếp trong mảng –

26

NSDictionary có phương pháp gọn gàng này được gọi là allKeys.

Nếu bạn muốn sắp xếp mảng, keysSortedByValueUsingComparator: sẽ thực hiện thủ thuật.

giải pháp của Richard cũng làm việc nhưng làm cho một số cuộc gọi thêm bạn không nhất thiết cần:

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

Tôi đã chỉnh sửa câu hỏi của mình, tôi nghĩ rằng nó được ngụ ý rằng các khóa phải theo thứ tự bằng giá trị khóa – Eric

+0

Tôi đang yêu cầu trợ giúp về việc phân loại. – Eric

+0

'keysSortedByValueUsingComparator:' sẽ thực hiện sắp xếp này. –

14

Dưới đây là một giải pháp:

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

hoạt động chính xác cho chuỗi chỉ bắt đầu bằng chữ cái, nhưng khi có chuỗi bắt đầu bằng số 10, chuỗi bắt đầu giữa chuỗi đầu tiên bắt đầu bằng "A" và chuỗi thứ ba bắt đầu bằng "A" – ViruMax

+0

Kiểm tra câu trả lời ở trên, trực quan và súc tích hơn , mặc dù điều này cũng giống như vậy. – nemesis

13

Giải pháp đơn giản nhất:

[dictionary keysSortedByValueUsingSelector:@selector(compare:)]

+1

cách viết hàm so sánh –

+0

Vui lòng giải thích phương pháp so sánh. – Tuhin

+0

Đối với các loại hiện có (ví dụ: NSString), phương thức đó đã tồn tại. Đối với bất kỳ thứ gì bạn tự tạo, phương thức sẽ trả về NSOrderedAscending, NSOrderedSame hoặc NSOrderedDescending, tùy thuộc vào thứ tự. Xem tài liệu cho 'compare: options: range:' để biết thêm thông tin. – dgatwood

2

Ở đây tôi đã làm một cái gì đó như thế này:

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