Stu*_*ssa 71 iphone macos cocoa cocoa-touch objective-c
给定一个NSArray
的NSDictionary
对象(含类似的对象和密钥)是有可能写出执行地图指定的键的阵列?例如,在Ruby中,它可以通过以下方式完成:
array.map(&:name)
Run Code Online (Sandbox Code Playgroud)
Jus*_*son 125
它只保存了几行,但我在NSArray上使用了一个类别.您需要确保您的块永远不会返回nil,但除此之外,对于-[NSArray valueForKey:]
无法工作的情况,它可以节省时间.
@interface NSArray (Map)
- (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block;
@end
@implementation NSArray (Map)
- (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;
}
@end
Run Code Online (Sandbox Code Playgroud)
用法很像-[NSArray enumerateObjectsWithBlock:]
:
NSArray *people = @[
@{ @"name": @"Bob", @"city": @"Boston" },
@{ @"name": @"Rob", @"city": @"Cambridge" },
@{ @"name": @"Robert", @"city": @"Somerville" }
];
// per the original question
NSArray *names = [people mapObjectsUsingBlock:^(id obj, NSUInteger idx) {
return obj[@"name"];
}];
// (Bob, Rob, Robert)
// you can do just about anything in a block
NSArray *fancyNames = [people mapObjectsUsingBlock:^(id obj, NSUInteger idx) {
return [NSString stringWithFormat:@"%@ of %@", obj[@"name"], obj[@"city"]];
}];
// (Bob of Boston, Rob of Cambridge, Robert of Somerville)
Run Code Online (Sandbox Code Playgroud)
Jer*_*myP 74
我不知道Ruby的功能是什么,但我认为你正在寻找NSArray的-valueForKey实现:.这将发送-valueForKey:
到数组的每个元素并返回结果数组.如果接收数组中的元素是NSDictionaries,-valueForKey:
则几乎相同-objectForKey:
.只要密钥不以一个开头,它就会工作@
tot*_*rio 35
总结所有其他答案:
Ruby(如问题所示):
array.map{|o| o.name}
Run Code Online (Sandbox Code Playgroud)
Obj-C(带valueForKey):
[array valueForKey:@"name"];
Run Code Online (Sandbox Code Playgroud)
Obj-C(带valueForKeyPath,参见KVC集合运算符):
[array valueForKeyPath:@"[collect].name"];
Run Code Online (Sandbox Code Playgroud)
Obj-C(使用enumerateObjectsUsingBlock):
NSMutableArray *newArray = [NSMutableArray array];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[newArray addObject:[obj name]];
}];
Run Code Online (Sandbox Code Playgroud)
array.map { $0.name }
Run Code Online (Sandbox Code Playgroud)
并且,有几个库允许您以更多功能的方式处理数组. 建议Cocoa Pods安装其他库.
Sen*_*ful 19
更新:如果您使用的是Swift,请参阅地图.
BlocksKit是一个选项:
NSArray *new = [stringArray bk_map:^id(NSString *obj) {
return [obj stringByAppendingString:@".png"];
}];
Run Code Online (Sandbox Code Playgroud)
Underscore是另一种选择.有一个map
功能,这是网站上的一个例子:
NSArray *tweets = Underscore.array(results)
// Let's make sure that we only operate on NSDictionaries, you never
// know with these APIs ;-)
.filter(Underscore.isDictionary)
// Remove all tweets that are in English
.reject(^BOOL (NSDictionary *tweet) {
return [tweet[@"iso_language_code"] isEqualToString:@"en"];
})
// Create a simple string representation for every tweet
.map(^NSString *(NSDictionary *tweet) {
NSString *name = tweet[@"from_user_name"];
NSString *text = tweet[@"text"];
return [NSString stringWithFormat:@"%@: %@", name, text];
})
.unwrap;
Run Code Online (Sandbox Code Playgroud)
我认为valueForKeyPath是一个不错的选择.
坐在下面有非常酷的例子.希望它有所帮助.
http://kickingbear.com/blog/archives/9
一些例子:
NSArray *names = [allEmployees valueForKeyPath: @"[collect].{daysOff<10}.name"];
NSArray *albumCovers = [records valueForKeyPath:@"[collect].{artist like 'Bon Iver'}.<NSUnarchiveFromDataTransformerName>.albumCoverImageData"];
Run Code Online (Sandbox Code Playgroud)