具有任意排序的 NSSortDescriptor

Posted

技术标签:

【中文标题】具有任意排序的 NSSortDescriptor【英文标题】:NSSortDescriptor with arbitrary sorting 【发布时间】:2011-11-25 15:11:40 【问题描述】:

我无法理解如何使用 NSSortDescriptor 进行任意排序。

我想做这样的事情:

NSArray *sortAlgorithm = [NSArray arrayWithObjects:@"@", @"#", @"!", @"&", @"r", @"a", nil];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" 
                                                               ascending:YES 
                                                              comparator:
    ^(id obj1, id obj2) 
        NSComparisonResult comparisonResult;
        //Some code that uses sortAlgorithm.
        return comparisonResult;
    
];

这将通过键 name 对对象进行排序,以便任何以 @ 开头的键,例如@home,将出现在任何以 r 开头的键之前,例如radical,这又会出现在任何以 a 开头的键之前,例如anything.

以上只是一个例子。重点是启用完全任意的排序。

这将用于 NSFetchedResultsController。

//一些使用 sortAlgorithm 的代码的代码是什么样的?

编辑:

围绕我尝试实现 sortDescriptor 的代码,作为 pr。 occulus'建议:

- (NSFetchedResultsController *)fetchedResultsController 
    if (__fetchedResultsController)
        return __fetchedResultsController;

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    fetchRequest.entity = [NSEntityDescription entityForName:@"Tag" inManagedObjectContext:self.temporaryManagedObjectContext];

    //NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO comparator:^(id obj1, id obj2) 

        NSArray *sortAlgorithm = [NSArray arrayWithObjects:@"#", @"!", @"@", @".", nil];

        NSString *obj1FirstChar = [(NSString *)obj1 substringToIndex:1];
        NSString *obj2FirstChar = [(NSString *)obj2 substringToIndex:1];
        int idx1 = [sortAlgorithm indexOfObject:obj1FirstChar];
        int idx2 = [sortAlgorithm indexOfObject:obj2FirstChar];

        if ( idx1 < idx2 )
            return NSOrderedAscending;
        else if ( idx1 > idx2 )
            return NSOrderedDescending;
        else
            return NSOrderedSame;
    ];

    fetchRequest.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
    fetchRequest.fetchBatchSize = 20;        

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.temporaryManagedObjectContext sectionNameKeyPath:nil cacheName:@"Tags"];

    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [self.fetchedResultsController performFetch:nil];

    return __fetchedResultsController;

注释掉的 sortDescriptor 有效。

在实体“Tag”的对象上肯定有一个名为name 的属性。但即使没有,这似乎也不是问题。 Xcode 似乎甚至没有编译那行代码(sortDescriptor),这听起来很荒谬。断点工作得很好,但没有在特定的代码行上中断。

【问题讨论】:

最近遇到了同样的问题。我最后买了Don的theory:***.com/questions/4789782/… 【参考方案1】:

您需要将obj1obj2字符串的第一个字符提取为NSStrings,在您的任意排序数组中找到它们的索引,然后比较位置。

类似这样的:(将此代码放入您的 ^ 块中)

NSString *obj1FirstChar = [(NSString *)obj1 substringToIndex:1];
NSString *obj2FirstChar = [(NSString *)obj2 substringToIndex:1];
int idx1 = [sortAlgorithm indexOfObject:obj1FirstChar];
int idx2 = [sortAlgorithm indexOfObject:obj2FirstChar];

// NOTE: we haven't dealt with the case where one of the
// chars wasn't found in the array of characters. A strategy
// for this would need to be decided.

if (idx1 == idx2) 
    return NSOrderedSame;

if (idx1 < idx2) 
    return NSOrderedAscending;

return NSOrderedDescending;

未经测试,可能需要稍作调整。注意大小写字符差异。

更新: 使用自定义排序描述符和 SQL 支持的核心数据存储似乎存在问题。请参阅this question 了解更多信息。

【讨论】:

我实现了您的建议,为了测试,我将源限制为仅包含在 sortAlgorithm 数组中找到的字符。绝对没有任何反应。甚至超出了我的预期:我在 NSSortDescriptor 的定义处设置了一个断点,它永远不会中断。如果我在指令之前或之后设置断点,它就会中断。 Xcode 很简单,而且非常不方便地跳过了我对您的解决方案进行测试的尝试……我想我会在解决这个新问题时发表这条评论,以防其他人知道这一点。 我相信我上面给出的算法是正确的。正如您所注意到的,它甚至可能没有被使用/调用。 您能否发布代码以说明您实际请求排序的方式?即您使用 NSSortDescriptor 的位置。听起来排序描述符从未被使用过。您的对象上是否肯定有一个名为“name”且类型为 NSString * 的属性? 用代码更新问题。是的,您的代码看起来不错,但似乎没有使用排序描述符。 嗨,Stian,使用核心数据和自定义排序描述符似乎存在已知错误。我已经更新了上面的答案以反映这一点,请参阅最后一点。

以上是关于具有任意排序的 NSSortDescriptor的主要内容,如果未能解决你的问题,请参考以下文章

排序区间查询

1023.Excel排序

实用且有效的排序算法

实用且有效的排序算法

算法刷题AcWing 113. 特殊排序——二分

二叉搜索树BST