views:

712

answers:

4

In Objective C, is there a one-liner or something small to remove (shorten by one) and return the first element of an array, regardless of its index?

+2  A: 

I don't know of a method that returns the item removed, but you can do this using a combination of NSArray#objectAtIndex:0 and NSMutableArray#removeObjectAtIndex:0. I suppose you could introduce a new method category on NSMutableArray that implements a shift method.

Jeffrey Hantin
I was under the impression that when I removedObjectAtIndex:0 I would be left with an array that started with an index of 1, like you may find in PHP. But as it turns out, bumping that one off (it being the oldest I have added to the array) is enough for what I'm doing.
ojreadmore
The linked documentation says it behaves similarly to shift, sliding the other elements down.
Jeffrey Hantin
If you really want a single method call, see my answer for a sample category declaration that adds what you need.
Quinn Taylor
+1  A: 

Cocoa array objects (NSArray/NSMutableArray) do not provide a one-line equivalent — you would have to read the object first, then remove it. The fact that these classes provide the methods -lastObject and -removeLastObject but not -firstObject and -removeFirstObject should be a reminder that removing from the front of an array is usually an inefficient operation, since the contents must be shifted (copied) one position forward. This is particular true for arrays in C, which are intrinsically tied with pointers.

If you're working with anything but primitive data types and/or very small arrays, you might want to consider that the behavior of "shifting off" the first element is indicative of a queue data structure. For details on how you might create a queue for objects, see this SO question. Personally, my opinion for that question is that a real queue class provides the cleanest programming idiom. You can even define your own method (perhaps as a category on NSMutableArray or another class) that does provide a one-liner to do what you want:

@interface NSMutableArray (QueueOneLiner)
  - (id) removeAndReturnFirstObject; // Verbose, but clearer than "shift"
@end

@implementation NSMutableArray (QueueOneLiner)
  - (id) removeAndReturnFirstObject {
    id object = [[self objectAtIndex:0] retain];
    [self removeObjectAtIndex:0];
    return [object autorelease];
  }
@end

However, by that point the solution will likely cause more overhead than it's worth, depending on the importance you place on simplicity versus performance of the code that uses it.

Quinn Taylor
Your QueueOneLiner might return an invalid object. The removeObjectAtIndex:0 will release "object" which may prematurely deallocate it if garbage collection is not used. You should retain and then autorelease the object before removing it from the array.
dreamlax
An excellent point! Edited to include your suggestion.
Quinn Taylor
+2  A: 

That would be a poor thing to do.

Objective-C on the iPhone can actually use most of the performance perks of C.

If you look at some of my other posts, you'll see I'm ADAMANTLY against premature optimization, but when you are coding at the C level, there are just some things you don't do unnecessarilly.

  • Move memory
  • Duplicate structures
  • Allocate sparsely populated memory blocks
  • Inner loops
  • ... (There are lots more, but my C-life is rusty and, as I said, I'm anti-optimization)

What you probably want is a well-implemented queue. Something that pre-allocates a large enough circular memory structure and then has two pointers that track the first and last bytes.

I'd be pretty surprised to hear that Objective-C didn't have a queue data structure.

Also, don't strive for the one-liners. All the stuff about terse code is overrated. If it makes more sense to call a method, so be it.

Bill K
perl "arrays" are more like a well-implemented queue than a C array; they have stored offsets to the "first" and last elements and intelligently preallocate where needed.
ysth
All the more reason to use a Queue on Objective-C then. Most interpreted languages are around 100x slower than the compiled languages--at that rate, the concerns are completely different and it totally makes sense that all arrays would have the overhead of a queue, but you won't find anything like that in the C-based languages.
Bill K
A: 

If you have an array obj *arr where obj is a class/typename and arr is the array, you can just say arr+1 to get the array without the first element.

Blindy