如果我使用比较对对象进行排序,如果其中一个对象为零,我如何告诉它不排序?
Posted
技术标签:
【中文标题】如果我使用比较对对象进行排序,如果其中一个对象为零,我如何告诉它不排序?【英文标题】:If I'm sorting objects using compare, how do I tell it to not sort if one of the objects is nil? 【发布时间】:2013-09-01 20:52:23 【问题描述】:假设我有以下代码块:
[allKeys sortUsingComparator:^NSComparisonResult(id obj1, id obj2)
NSDictionary *firstArticle = [articles objectForKey:(NSString *)obj1];
NSNumber *firstSortID = [firstArticle objectForKey:@"sort_id"];
NSDictionary *secondArticle = [articles objectForKey:(NSString *)obj2];
NSNumber *secondSortID = [secondArticle objectForKey:@"sort_id"];
if (firstSortID == nil || secondSortID == nil)
return nil;
else
return [secondSortID compare:firstSortID];
];
我收到警告:
指向整数转换的不兼容指针从 a 返回“void *” 结果类型为“NSComparisonResult”(又名“枚举”)的函数 NSComparisonResult')
但基本上,如果其中一个为 nil,它会崩溃,因为比较没有意义。我怎么告诉它,如果它是 nil,不要打扰,停下来。
【问题讨论】:
警告:您返回 nil 而不是 NSComparisonResult ... 是什么保存了已排序的对象?通常的 NS 数据结构都没有存储 nil。 【参考方案1】:您必须决定如何对 nil
值进行排序。他们很可能应该排在列表的末尾。你想要这样的东西:
if (firstSortID)
if (secondSortID)
// Both set, compare
NSComparisonResult result = [firstSortID compare:secondSortID];
if (result == NSOrderedSame)
// optionally do another comparison on a secondary value
// result = ...
return result;
else
// Have 1st but not 2nd
return NSOrderedAscending;
else
if (secondSortID)
// Have 2nd but not 1st
return NSOrderedDescending;
else
// Both nil, treat as the same
// Another option here is to look at another value in the dictionary to be used as a secondary sort
return NSOrderedSame;
【讨论】:
最简单的解决方案,但是带有 nil 属性的对象的顺序会不稳定。 当两个值都是nil
时,如果使用代码注释中所述的辅助值,则解决此问题。
无论对象状态如何,我都无法思考这是否会产生有保证的稳定排序。 IE。仅在 nil,nil
上下文中切换排序键有效吗?
其实,如果两个值都不是nil
并且compare:
的结果返回NSOrderedSame
,你也需要二次(甚至更高)排序。我会用这个细节更新我的答案。【参考方案2】:
您不能使用sortUsingComparator:
提前终止排序。因此,您必须对 nil
值进行排序 - 只需确定 nil
应该是最小值还是最大值,然后根据需要返回 NSOrderedDescending
、NSOrderedAscending
或 NSOrderedSame
。
如果您需要知道您是否点击了nil
,请在您的块中设置一个标志,然后您可以对其进行测试。该标志需要使用 __block
限定符声明,以便可以在您的块中进行修改,例如:
__block BOOL nilFound = NO;
[allKeys sortUsingComparator:^NSComparisonResult(id obj1, id obj2)
NSDictionary *firstArticle = [articles objectForKey:(NSString *)obj1];
NSNumber *firstSortID = [firstArticle objectForKey:@"sort_id"];
NSDictionary *secondArticle = [articles objectForKey:(NSString *)obj2];
NSNumber *secondSortID = [secondArticle objectForKey:@"sort_id"];
// set flag - could alternatively be set during comparison logic below
if (firstSortID == nil || secondSortID == nil)
nilFound = YES;
// actual comparison, allowing for nil values
...
];
// was a nil found?
if (nilFound) ...
附录
其他人提出了稳定排序的问题,您应该能够通过使用原始键来解决这个问题,例如:
if (firstSortID == nil)
if (secondSortID == nil)
// both nil - use original keys as secondary sort, obj1 & obj2 are strings
return [obj1 compare:obj2];
else
return NSSortAscending;
else
return secondSortID == nil ? NSSortDescending : [secondSortID compare:firstSortID];
(您可以切换 NSSortAscending
和 NSSortDescending
以将 nil
值分组在另一端。)
【讨论】:
您不需要让== nil
检查类型是否可以是 id。 if (!firstSortID || !secondSortID)
已经足够好了。
@OliverAtkinson - 任何对象引用(或 C 指针 et al.)都可以按照您的建议进行测试。选择很大程度上取决于风格。以上是关于如果我使用比较对对象进行排序,如果其中一个对象为零,我如何告诉它不排序?的主要内容,如果未能解决你的问题,请参考以下文章
js使用Array.prototype.sort()对数组对象排序的方法