【问题标题】:Sort a NSArray of numbers in ascending order but send zeros at the end按升序对数字的 NSArray 进行排序,但最后发送零
【发布时间】:2013-05-02 12:46:05
【问题描述】:

我有一个简单的NSArray,包含NSNumbers。

我以这种方式按升序对数组进行排序:

NSSortDescriptor *lowestToHighest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES];
[_scores sortUsingDescriptors:[NSArray arrayWithObject:lowestToHighest]];

我的问题是,我希望包含 0NSNumbers 位于末尾而不是开头。这是我可能需要排序的数组类型(包含一些空的 NSNumbers 仅用于示例):

0
25
12
0
8
0

我的代码当然是这样对数组进行排序的:

0
0
0
8
12
25

我想要的是这样的:

8
12
25
0
0
0

当然,我可以通过删除带有0 的行并在末尾添加它们来手动重新排序,但我正在寻找最干净的解决方案。

【问题讨论】:

  • 8, 12, 0 是升序还是降序?您是如何将nil 存储在NSArray 中的?或者你确定你有NSNumber 实例?他们不是NSStrings,而是?
  • @H2CO3 同意作者如何在 NSArray 中存储 nil 值以表示 NSNumber
  • 它是一个升序,除了值0,它被发送到数组的末尾。它们实际上不是“零”对象,而是未初始化的 NSNumber。在调试控制台中显示为 [5] id 0x00000000
  • 我从帖子中删除了它们,因为它确实很奇怪。对此感到抱歉。
  • @rdurand 0x00000000NULL 指针 -> 它们实际上是 nil 你是如何将它们放入数组中的?这是某种CFArray 桥接吗?

标签: ios objective-c nsarray nssortdescriptor


【解决方案1】:

使用comparator 对数组进行排序。

NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id obj1, id obj2) {

    if ([obj1 integerValue] == 0 && [obj2 integerValue] == 0)
    {
        return (NSComparisonResult)NSOrderedSame;
    }
    if ([obj1 integerValue] == 0)
    {
        return (NSComparisonResult)NSOrderedDescending;            
    }
    if ([obj2 integerValue] == 0)
    {
         return (NSComparisonResult)NSOrderedAscending;
    }

    if ([obj1 integerValue] > [obj2 integerValue]) 
    {
        return (NSComparisonResult)NSOrderedDescending;
    }

    if ([obj1 integerValue] < [obj2 integerValue]) 
    {
        return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
}];

【讨论】:

  • 看起来像我要找的东西。谢谢!我想过使用比较器,但无法使用。
  • @gokhancokkececi 你的意思是 id1 和 id2 - 这显然是一个错字,现在已修复。
【解决方案2】:

这会解决你的问题,

NSArray *sortedScores = [_scores sortedArrayUsiHelperComparator:^(id obj1, id obj2){
    if([obj1 integerValue]==0 && [obj2 integerValue]==0){
        return (NSComparisonResult) NSOrderedSame;
    }else if([obj1 integerValue]==0){
        return (NSComparisonResult) NSOrderedDescending;
    }else if([obj2 integerValue]==0){
        return (NSComparisonResult) NSOrderedAscending;
    }
    if([obj1 integerValue] >[obj2 integerValue]) return (NSComparisonResult) NSOrderedDescending;
    if([obj1 integerValue] <[obj2 integerValue]) return (NSComparisonResult) NSOrderedAscending;
    return (NSComparisonResult) NSOrderedSame;

}];

【讨论】:

  • 谢谢,但我认为 JeremyP 的答案更准确,因为他比较的是 [id1 integerValue] == 0 而不是 obj1==nil。就我而言,我希望零在最后,而不是 nil 对象。
  • 在你的问题中,有 nil 值。我为此编写了代码。你已经改变了问题。现在检查!
  • 无论如何,您都不能将nils 放在NSArray 中。
  • @JeremyP,这是添加空值的方法:[_scores addObject:[NSNull null]];
  • @ThilinaHewagama 是的,但 [NSNull null] 不是 nil。 [NSNull null] 是一个对象,表示集合中不能保存 nil 的 null 值。一个占位符,如果你愿意的话。
【解决方案3】:

方法一:

  • 第 1 步:对数组进行排序。

  • 第 2 步:将零移动到数组的末尾。

方法二:

  • 第 1 步:编写一个比较器函数,将 0 排序在任何其他值之后。

  • 第 2 步:对数组进行排序。

【讨论】:

  • 谢谢,但这不是我想要的,正如我在问题中所说的那样。
  • @Monolo:当我发表评论时,Caleb 只建议了第一种方法。我在我的问题中说,我知道我可以做到这一点,但我正在寻找比“排序然后移动零”更干净的东西。方法 2 正是 JeremyP 在他的回答中所说的,这是在 Caleb 编辑自己的答案之前出现的。
【解决方案4】:

@JeremyP 的回答提供了正确的排序,可能就是您所追求的。

但是,为了完整起见,可以使用过滤器和标准 compare: 方法:

NSArray *numbers = @[@12, @0, @10, @15, @0, @3];

NSArray *sortedPositiveNumbers = [[numbers filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self > 0"]] sortedArrayUsingSelector:@selector(compare:)];
NSArray *zeroes = [numbers filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self = 0"]];

NSArray *result = [sortedPositiveNumbers arrayByAddingObjectsFromArray:zeroes];

感谢 Caleb 的火花。

【讨论】:

    【解决方案5】:

    您可以使用NSPredicate 过滤您不想要的值..

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self > 0"];
    NSMutableArray *filteredArray = [[_scores filteredArrayUsingPredicate:predicate] mutableCopy];
    NSSortDescriptor *lowestToHighest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES];
    [filteredArray sortUsingDescriptors:[NSArray arrayWithObject:lowestToHighest]];
    

    【讨论】:

    • 谢谢,但我相信这会删除所有的零,对吧?我想将它们保留在数组中,但最后。无论如何,谢谢,这可能会在未来为我服务。
    • @rdurand 是的,该代码在 1 行中删除了所有低于 0 的值。然后它会根据你想要的顺序排序。
    猜你喜欢
    • 1970-01-01
    • 2021-06-10
    • 2011-03-25
    • 1970-01-01
    • 1970-01-01
    • 2015-07-15
    • 2010-11-23
    • 2012-11-29
    相关资源
    最近更新 更多