繁体   English   中英

使用NSSortDescriptor对NSDictionary对象的NSArray进行排序

[英]Sort NSArray of NSDictionary objects using NSSortDescriptor

我有一系列词典,其中包含有关高分的信息。 我试图弄清楚如何按照字典中的不同值对它们进行排序,但无法使其正常工作。

下面显示的示例尝试按“分数”进行排序:

NSDictionary *highScoreDictionary1 = @{@"Score" : @52, @"Duration" : @230 , @"Date" : [NSDate date]};
NSDictionary *highScoreDictionary2 =  @{@"Score" : @23, @"Duration" : @230 , @"Date" : [NSDate date]};
NSDictionary *highScoreDictionary3 = @{@"Score" : @35, @"Duration" : @230 , @"Date" : [NSDate date]};

NSArray *highScoresArray = @[highScoreDictionary1, highScoreDictionary2, highScoreDictionary3];

NSSortDescriptor *highScoreSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"Score" ascending:YES];  // Sort by Score
NSArray *sortDescriptorArray = [NSArray arrayWithObject:highScoreSortDescriptor];

[highScoresArray sortedArrayUsingDescriptors:sortDescriptorArray];

我从NSLog(@"sorted array of dictionaries: %@", highScoresArray);获得的输出NSLog(@"sorted array of dictionaries: %@", highScoresArray); 是:

sorted array of dictionaries: (
        {
        Date = "2014-09-01 19:38:00 +0000";
        Duration = 230;
        Score = 52;
    },
        {
        Date = "2014-09-01 19:38:00 +0000";
        Duration = 230;
        Score = 23;
    },
        {
        Date = "2014-09-01 19:38:00 +0000";
        Duration = 230;
        Score = 35;
    }
)

我该如何补救? 我在这里错过了什么吗,因为似乎字典没有按分数排序。

highScoresArray = [highScoresArray sortedArrayUsingDescriptors:sortDescriptorArray];

您正在尝试对不可变的NSArray进行排序。 您需要使用sort函数来创建可变数组,即

替换您的:

[highScoresArray sortedArrayUsingDescriptors:sortDescriptorArray];

有:

NSMutableArray *newArray = [[NSMutableArray alloc] initWithArray:[highScoresArray sortedArrayUsingDescriptors:@[highScoreSortDescriptor]]];

我已经对此进行了测试,它似乎可以工作。

试试这个方法

NSArray *sortedArray;
sortedArray = [highScoresArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    NSDictionary *first = (NSDictionary*)a;
    NSDictionary *second = (NSDictionary*)b;

    int firstScore = [first objectForKey:@"score"];
    int secondScore = [second objectForKey:@"score"];

    if(firstScore > secondScore)
    {
        return NSOrderedDescending;
    }
    else if (firstScore < secondScore)
    {
        return NSOrderedAscending;
    }

    return NSOrderedSame;
}];

这里得到代码

如果您愿意,这是我自己手动实现的排序方法,在您的情况下,请像这样使用它

// you could also pass "DESC" for descending order
NSMutableArray* copiedArray = [[NSMutableArray alloc] initWithArray:highScoresArray];
[self sortArray:copiedArray inOrder:@"ASC" basedOnField:@"Score" args:-1];
// Now copiedArray contains a sorted array :)

这是完整的代码(2个方法,一个主要方法和一个辅助方法),将它们复制到某个类中,以便上面的代码起作用。

/*
 * This method sorts a given array based on the given field name and the given sorting order
 * fieldName could be nil if the comparison shall happen directly on the array items
 * args contain the array index of the value to compare if "field name" pointed to an array or -1
 */
- (void)sortArray:(NSMutableArray*)array
          inOrder:(NSString*)sortingOrder
     basedOnField:(NSString*)fieldName
             args:(int)args {
    for (int i = 1; i < array.count; i++) {
        // Start the insertion sort algorithm
        int j = i;

        // Get the current value and one before it
        id currentValue = [self itemInArray:array
                                    atIndex:j
                                  fieldName:fieldName
                                       args:args];

        id previousValue = [self itemInArray:array
                                     atIndex:j-1
                                   fieldName:fieldName
                                        args:args];

        // Set the comparison result based on the user request
        NSComparisonResult requiredResult = NSOrderedDescending;
        if ([sortingOrder compare:@"ASC"] == NSOrderedSame) {
            requiredResult = NSOrderedAscending;
        }

        while ((j > 0) && ([previousValue compare:currentValue] == requiredResult)) {
            // Swap the current and previous objects
            id temp = array[j];
            array[j] = array[j-1];
            array[j-1] = temp;

            // Get back one step and get the new current and previous values
            j--;
            if (j == 0) {
                break;
            }

            currentValue = [self itemInArray:array
                                     atIndex:j
                                   fieldName:fieldName
                                        args:args];

            previousValue = [self itemInArray:array
                                      atIndex:j-1
                                    fieldName:fieldName
                                         args:args];
        }
    }
}

// This method gets an item from the array based on the given index and the field name if the item is an object, as well as a specific member of that item if it's an array (index is passed in args)
- (id)itemInArray:(NSArray*)array
          atIndex:(int)index
        fieldName:(NSString*)fieldName
             args:(int)args {

    // Get the item at the given index
    id value = array[index];

    // Get the sepcific field from it if it's an object
    if (fieldName != nil) {
        value = [value valueForKey:fieldName];
    }

    // Get the specific value if the field is an array
    if ([value isKindOfClass:[NSArray class]]) {
        value = value[args];
    }

    return value;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM