1

我正在Core Data使用 an 从存储中获取数据NSFetchRequest并将该数据存储在一个中array- 一切都很好。作为下一步,我想array使用NSSortDescriptors这样的排序:

array = [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:
            [NSSortDescriptor sortDescriptorWithKey:@"score" ascending:NO],
            [NSSortDescriptor sortDescriptorWithKey:@"score" ascending:NO comparator:^NSComparisonResult(id obj1, id obj2) {
                    if ([[[array objectAtIndex:[obj2 integerValue]] valueForKey:@"lessImportantItems"] containsObject:[array objectAtIndex:[obj1 integerValue]]]) {
                        return (NSComparisonResult)NSOrderedAscending;
                    } else {
                        return (NSComparisonResult)NSOrderedDescending;
                    }
                }],
            [NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:NO], nil]];

我遇到的问题是NSComparator第二个中的块NSSortDescriptor没有被调用(我试图NSLog)。为了给我的数据结构一些背景知识,这里是相关的Core Data对象图部分:

http://screencast.com/t/AOY6IdNFWoK

该应用程序所做的是将项目相互比较。作为第一步,配对比较中的获胜者会获得一个score增量。lessImportantItems但我也标记了配对优先级,即我添加了从赢家到输家的一对多关系。所以,在我的数组中,我首先尝试按 排序score,然后,当scores 相等时,我也尝试按配对优先级排序。

也许是因为我连续两次score用作比较器?key但是,另一方面,NSComparator不允许将 arelationship作为 a 传递key

我似乎无法破解这个。有人有什么想法吗?或者也许我应该采用不同的方法进行排序?

4

2 回答 2

1

第二个排序描述符对我来说没有任何意义。它将给定的比较器应用于score要比较的对象的属性。所以在比较器内部 obj1obj2是待比较对象的得分值。似乎您尝试使用以下对象获取基础对象

[array objectAtIndex:[obj1 integerValue]]
[array objectAtIndex:[obj2 integerValue]]

但这行不通。所以第二个排序描述符应该看起来像

[NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO
        comparator:^NSComparisonResult(Item *item1, Item *item2) {

        // compare item1, item2 ...
}];

但是接下来的问题出现了:如何根据优先级比较两个对象?您的代码基本上执行以下操作:

if ([item2 valueForKey:@"lessImportantItems"] containsObject:item1]) {
    return NSOrderedAscending;
} else {
    return NSOrderedDescending;
}

但这不是一个合适的比较器:

  • NSOrderedSame如果对象相等(不是“自反的”),它不会返回,
  • 对于两个“不相关的对象”,NSOrderedDescending无论顺序如何(不是“不对称”),它都会返回,
  • 它不检测是否item1只是间接相关item2(不是“传递”)。

但是如何对“不相关的对象”进行排序呢?没有唯一的解决方案。如果 B 和 C 都没有 A 重要,那么 A、B、C 和 A、C、B 都是有效解。比较 B 和 C 时,比较器应该返回什么?

所以我认为这不能用排序描述符来实现,你必须选择其他算法,例如“拓扑排序”

于 2013-08-14T13:16:10.117 回答
0

如果有人感兴趣,这就是我如何实现我所追求的排序。

我只使用NSSortDescriptor上面示例中的第一个来获得array排序依据score,然后我调用了进一步的排序方法array

array = [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:
            [NSSortDescriptor sortDescriptorWithKey:@"score" ascending:NO], nil];

array = [self applyMoreImportantPairOrdering:array];

这是方法:

+ (NSArray *)applyMoreImportantPairOrdering:(NSArray *)array {

    NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array];

    [array enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

        if ([[obj valueForKey:@"score"] integerValue] > 0) {

            NSMutableSet *lessImportantItemsSet = [NSMutableSet setWithSet:[obj valueForKey:@"lessImportantItems"]];

            for (int i = idx - 1; i >= 0; i--) {

                NSManagedObject *objAbove = [array objectAtIndex:i];

                if ([[obj valueForKey:@"score"] integerValue] == [[objAbove valueForKey:@"score"] integerValue]) {

                    if ([lessImportantItemsSet containsObject:objAbove]) {

                        NSUInteger idxAbove = [mutableArray indexOfObject:objAbove];

                        [mutableArray removeObject:obj];
                        [mutableArray insertObject:obj atIndex:idxAbove];
                    }
                }
            }
        }
    }];

    return [NSArray arrayWithArray:mutableArray];
}

我需要的原因是因为当我在 an 中lessImportantItemsSet移动(删除和插入)an时,它会失去它的关系。这样我在完成特定.itemarraylessImportantItemsitemitem

于 2013-08-27T15:41:11.590 回答