开发者

Cocoa/Objective-C - How do I step through an array?

Not sure if I am wording this correctly but what I need to do is iterate through an array sequentially but by 2 or 3 or 4 i开发者_如何学Gondices.

So you can iterate through an array like this

for(id arrayObject in NSArray) { 
    //do something amazing with arrayObject
}

which will iterate sequentially through each indexed object, [NSArray objectAtIndex: 0], [NSArray objectAtIndex: 1], etc.

so what if I just want object 0, 4, 8, 12, etc.

Thanks


Not quite. The way you wrote it, you are omitting the class of the arrayObject, and you are iterating through the NSArray class name rather than an instance. Thus:

for (id arrayObject in myArray) {
    // do stuff with arrayObject
}

where myArray is of type NSArray or NSMutableArray.

For instance, an array of NSStrings

for (NSString *arrayObject in myArray) { /* ... */ }

If you want to skip parts of the array, you will have to use a counter.

for (int i=0; i< [myArray count]; i+=4) {
    id arrayObject = [myArray objectAtIndex:i]; 
    // do something with arrayObject
}


You could use enumerateObjectsUsingBlock: and check the index inside the block:

[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if( 0 == idx % 3 ){
        // Do work
    }
    else{
        // Continue enumeration
        return;
    }
}];

This would also allow you to operate on non-stride-based selections of your array, if necessary for some reason, e.g., if( (0 == idx % 3) || (0 == idx % 5) ), which would be much more difficult with a plain for loop.


I'd like to add, that there are also block-based enumeration methods, you could use.

NSMutableArray *evenArray = [NSMutableArray array];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if (idx % 4 == 0) 
        [evenArray addObject:obj];
}];

Now evenArray will contain the objects with the indexes 0,4,8,… in the original array.

But often one will want to have just the filtered objects in the original array, and won't need a additionally mutable array.

I wrote some block-based convenient methods to achieve this:

array = [array arrayByPerformingBlock:^id(id element) {
    return element;
} ifElementPassesTest:^BOOL(id element) {
    return [array indexOfObject:element]%4 == 0;
}];

This will have the same result but hides the boilerplate code of creating and filling a mutable array.

You'll find my arraytools on GitHub.


You can do this with an NSEnumerator:

NSEnumerator *arrayEnum = [myArray objectEnumerator]; //Or reverseObjectEnumerator
for (MyThingy *thingy in arrayEnum) {
    doThingyWithThingy(thingy);

    [arrayEnum nextObject]; //Skip element
}

You can have zero or more nextObject messages at either point. For every third object, you would have two nextObjects at the end of the loop:

for (MyThingy *thingy in arrayEnum) {
    doThingyWithThingy(thingy);

    //Skip two elements
    [arrayEnum nextObject];
    [arrayEnum nextObject];
}

Basically, this is the same way you gather multiple objects in a single pass through the loop, only without actually using the other objects.

You can also have zero or more nextObject messages before the loop to skip some number of objects before the first one you want.

(I hope you're doing this to an array you read in, not one you generated yourself. The latter case is a sign that you should consider moving from array manipulation to model objects.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜