Geek just asked me:
“Can you do a ‘List Comprehension’ in Objective-C like you can in Python?”
First I had to ask him what the heck a “List Comprehension” was and he replied:
“listOfSquares = [x*x for x in listOfInts]“
ah, ok!
Seemed like it should be easy in ObjectiveC, but it takes a bit more code than in python!
Here’s my simple example for him:
// initialize a start array (a) and a destination array (b)
NSMutableArray * a = [NSMutableArray arrayWithObjects: @"Hello", @"Will This work?", @"can it work?", @"Yes!", nil];
NSMutableArray * b = [NSMutableArray arrayWithCapacity: [a count]];
NSLog(@"start array: %@", a );
// here's a simple List Comprehension (uppercase all the strings)
[a enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
[b addObject: [obj uppercaseString]];
}];
NSLog( @"ending array: %@", b );
Here’s the output:
2013-02-04 21:01:26.156 test[45743:403] start array: (
Hello,
"Will This work?",
"can it work?",
"Yes!"
)
2013-02-04 21:01:26.157 test[45743:403] ending array: (
HELLO,
"WILL THIS WORK?",
"CAN IT WORK?",
"YES!"
)
Update: Several people have pointed out on twitter that this is more like a map() operation in python but also some noted that List Comprehension is a a form of mapping but one with a compact syntax. In any case this was mostly about Geek having a way he did things in python and wondering what the closest equivalent was in ObjC. This is at least one approach.
Update2: And as xinsight points out, while Geek asked if there was a way to do this with blocks, the “old fashioned way” is in many respects much cleaner:
for ( id obj in a ) [b addObject: [obj uppercaseString]];
February 5, 2013 at 12:16 am |
Careful with insertObject:AtIndex: — from the docs:
“Note that NSArray objects are not like C arrays. That is, even though you specify a size when you create an array, the specified size is regarded as a “hint”; the actual size of the array is still 0. This means that you cannot insert an object at an index greater than the current count of an array.”
Also, i think a plain old for loop with addObject: to the target array would be cleaner. (Not sure about performance.)
February 5, 2013 at 11:24 am |
The indexes will always match in this case so it’ll be fine but addObject: would be safer if there’s a chance they’ll end up being different counts in the two lists.
Also a good point about a simple
for ( foo in a )(I’ve updated the post above).