如何在像obj-c的Map方法的ruby中迭代时跳过对象

使用这里的答案,这个方法在obj-c中实现类似于ruby的映射:

- (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block { NSMutableArray *result = [NSMutableArray arrayWithCapacity:[self count]]; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [result addObject:block(obj, idx)]; }]; return result; } 

我的问题是,如果在应用块时发生错误,我怎么能跳过一个对象? 通常要跳过枚举器中的某些内容,只需使用return命令,但这不是上述方法中的一个选项,因为该块应该返回一些内容。

在这个例子中,我使用return to skip但是得到一个错误:

 NSArray *mappedArray = [objArray mapObjectsUsingBlock:^(id obj, NSUInteger i) { // i don't want this obj to be included in final array // so I try to skip it return; // ERROR:incompatible block pointer types sending // 'void(^)(__strong id, NSUInteger)' to parameter of type // 'id(^)(__strong id, NSUInteger)' // else do some processing return soupedUpObj; }]; 

我目前的解决方法是简单地返回一个null对象,然后将它们从最终数组中删除。 但我相信一定有比这更好的方法。

如果实现与上面显示的类似,那么将块结果应用于中间值然后在将其添加到结果数组之前进行检查是有意义的。 像这样的东西:

 - (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block { NSMutableArray *result = [NSMutableArray arrayWithCapacity:[self count]]; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { id blockResult = block( obj, idx ); if( result != nil ){ [result addObject:blockResult]; } }]; return result; } 

一个快速的补救措施:编写自己的变体,它使用NSPointerArray而不是NSArray。 NSPointerArray可以保持为零。 然后可以保留顺序,并且可以使用nil来指示错误(假设NSNull是一个无法用于指示错误的有效值)。 使用NSPointerArray,您的块将返回nil。

这只是mapObjectsUsingBlock:来自的任何框架或库的限制(它不是标准的Apple API)。

但是,实现数组映射function并不困难,因此您可以轻松编写自己的版本来处理块参数中的nil返回值。