“List Comprehension” in Objective-C like in Python

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: (
"Will This work?",
"can it work?",
2013-02-04 21:01:26.157 test[45743:403] ending array: (

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]];

2 thoughts on ““List Comprehension” in Objective-C like in Python”

  1. 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.)

    1. 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).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: