【问题标题】:NSMutableArray Sort Using SelectorNSMutableArray 使用选择器排序
【发布时间】:2011-03-03 08:44:13
【问题描述】:

我用谷歌搜索过 stackoverflow,但没有得到满意的答案。

在文档中,它指出:

sortUsingSelector:对数组的排序 元素按升序排列,如 比较法确定 由给定的选择器指定。

  • (void)sortUsingSelector:(SEL) 比较器 参数比较器选择器 指定要使用的比较方法 比较数组中的元素。这 比较器消息被发送到每个 数组中的对象,并作为其 单个参数中的另一个对象 大批。比较方法应该 如果数组返回 NSOrderedAscending 小于参数, NSOrderedDescending 如果数组是 大于论点,并且 NSOrderedSame 如果它们相等。

我试图了解它的实际工作原理。所以如果我在我的对象中有这个方法 数组类:

- (NSComparisonResult) compareNames: (id) element
{
    return [userName compare: [element userName]];
}

然后执行它

[myArray sortUsingSelector:@selector(compareNames:);

它有效。问题是我不知道它为什么起作用。 NSComparisonResult 的返回类型 是升序、相同或降序。从我通过阅读文档得到的是 compareNames 方法被发送到 myArray 中的每个对象并比较选定的对象 对象属性(在本例中为 userName)与 userName 在另一个对象中 相同的数组。 (就像 [0] 数组与 [1] 数组进行比较)。我想知道这是怎么回事 整个过程正在进行中。

更新 1:多键排序算法

我错过了!在比较中。应该是这样的:

NSComparisonResult res;
res = [[self userName] compare: [element userName]];
if(res == NSOrderedSame) res = [[self email] compare: [element email]];
return res;

至于降序排序,您可以使用 switch 或 if 将“return res”替换为以下内容来恢复 NSComparisonResult 值:

switch (res)
    {
        case NSOrderedAscending:
            return NSOrderedDescending;
            break;
        case NSOrderedDescending :
            return NSOrderedAscending;
            break;
        default:
            return NSOrderedSame;
            break;
    }*/

【问题讨论】:

  • 你到底有什么不明白的?基本上,它比较所有对象对并交换它们,如果它们的顺序错误。 (但实际上,不必比较所有对,n*log(n) 就足够了。)
  • 总是按升序排序吗?如果我想按多个值排序怎么办。就像按名称排序,然后按电子邮件排序。

标签: objective-c sorting


【解决方案1】:

回答您在 cmets 中的子问题:

排序总是需要升序吗? - NSOrderedAscendingNSOrderedDescending 在这里只是象征性的,您最好将它们视为“对象在参数之前”和“对象在参数之后”按排序顺序。例如。如果您要存储NSNumber 的数组,则“1 compareTo:2”应返回NSOrderedAscending,如果您想按递增值排序,则应返回NSOrderedDescending,如果您希望按递减值排序。

如何使用多个键进行排序? - 任何排序算法只需要知道一个项目是在另一个之前、之后还是在同一位置。 如何你决定这取决于你。要使用两个排序键,那么在伪代码中算法是:

To compare item1 and item2
    order = [item1.key1 compareTo:item2.key1];
    if (order == NSOrderedSame) order = [item1.key2 compareTo:item2.key2];
    return order

根据需要扩展到更多键或更复杂的比较。


跟进评论:

抱歉,提供的算法确实进行了 2 键排序,并且通常组合键可能不会而且很浪费

英文中两个key的排序是这样的:首先比较每个对象的第一个key,如果比较不相等则返回它们的排序。如果它们比较相等,则继续并比较每个对象的第二个键并返回它们的顺序。

这正是上面的伪代码所做的。

由于多种原因,组合多个键存在问题:

  1. 您必须使用不能出现在键中的分隔符来组合它们。作为一个简单的例子,当你有两个人“jack yolander”和“jacky olander”时,考虑按名字、姓氏排序——天真的加入会为两者产生“jackyolander”,他们会排序相等。所以你需要一个不能出现在任何键中的分隔符。

  2. 如果键的类型不同,例如一个字符串和一个数字,你最终将它们全部转换为字符串来组合 - 浪费,甚至可能不准确。

  3. 简单地组合它们是浪费 - 你正在生成你不需要的对象。

等等。只需成对比较密钥,直到找到两个不同的密钥或到达最后一对。适用于任意数量、任意类型的键,不会造成浪费。

【讨论】:

  • 您提供的算法只对一个键进行排序。因为一旦你对所有 key1 进行排序,排序将使用 key2 重新排序所有排序数组。我已经尝试过了,但它没有给出我想要的结果。我不确定分类过程是如何在班级中进行的。但是我可以通过将两个键组合成单个 NSString 并仅使用一种比较方法对它们进行排序来获得我想要的结果。我已经包含了上面的代码。
  • 抱歉,提供的算法确实进行了 2 键排序,通常组合键可能不会而且很浪费。
  • 我错过了并输入了!在比较过程中。难怪它不会产生我期望的结果。你的工作完美。很抱歉,我在编辑或回复之前没有正确检查我的代码。并感谢您的详细回答。
【解决方案2】:

sortUsingSelector 将使用 Quicksort 或类似的排序算法对数组进行排序。排序算法需要能够比较要排序的集合中的两个项目,并确定它们在排序顺序中相对于彼此出现的位置。 A 应该出现在 B 之前、B 之后还是紧挨着它?您的自定义排序方法(在您的示例中为compareNames)是确定排序所需的所有排序算法。

查看Wikipedia entry for sorting algorithms 了解这方面的一些背景信息。

如果您搜索例如“排序使用选择器”。这不是特定于 Objective-C 的问题,几乎所有编程语言都有使用用户定义的比较函数进行排序的排序例程。

【讨论】:

    猜你喜欢
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多