Question

Consider a loop. I am also interested by fast enumerations. So, it could be

  • either a for(id obj in objects)
  • or a [objects enumerate... ]

I want to know if there is a classical or nice way (in Objective-C) to make a distinction between the first element of the loop and the others. Of course, if there is only a nice way to distinguish the last elements from the others, I am also interested.

Is there a classical or nice way to apply different instructions to the first or last element of a loop?

Was it helpful?

Solution

It's easiest with a classic for loop but since you want fast enumeration you need your own counter:

NSUInteger index = 0;
NSUInteger count = objects.count;
for (id obj in objects) {
    if (index == 0) {
        // first
    } else if (index == count - 1) {
        // last
    } else {
        // all others
    }

    index++;
}

If objects is an NSArray, you can do:

[objects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if (idx == 0) {
        // first
    } else if (idx == objects.count - 1) {
        // last
    } else {
        // all others
    }
}];

OTHER TIPS

Not sure what nice means, so here is my idea:

[array.firstObject doSomethingWithFirst]; // iOS 7 SDK or custom category

NSRange range = NSMakeRange(1, array.count - 2); //TODO: Check for short arrays.
for (id object in [array subarrayWithRange:range]) {
    [object doSomething];
}

[array.lastObject doSomethingWithLast];

It does what you want, you don't bother with counting indexes, uses fast enumeration, it's readable (first and last). The only weird thing on this is the NSRange part.

You may consider this nice.

If you use the common statement of FOR you can do that:

for (int i = 0; i < [myArray count]; i++)
{
    if(i == 0)
        NSLog("First");

    if(i == [myArray count] - 1)
        NSLog("Last");

    //rest of your code
}

Even i would recommend to use these NSArray method :-

 - (void)enumerateObjectsUsingBlock:(void (^)
   (id obj, NSUInteger idx, BOOL *stop))block

Keep in mind that enumerateObjectsUsingBlock does not guarantee about looping in ordered manner. A classic example for what you might be looking for:

const NSInteger sizeOfArray = 10;
NSInteger numbers[sizeOfArray] = {10,20,30,40,50,60,70,80,90,100};

NSInteger i = 0;

do {
    switch (i) {
        case 0:
            NSLog(@"First");
            break;
        case sizeOfArray:
            NSLog(@"Last");
            break;
        default:
            NSLog(@"All others");
            break;
    }
    NSLog(@"Number = %i", numbers[i++]);
}while (i < sizeOfArray);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top