13

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?

4
  • Are you talking about a bare C-style array, or something like an NSArray/NSMutableArray? Commented Jun 17, 2009 at 21:50
  • 1
    In the case of a bare C-style array you're in trouble before you get out of the gate: C-style arrays don't include their bounds/valid size information. I suppose you could pass a pointer to the valid size, but that gets ugly... Commented Jun 17, 2009 at 21:56
  • 1
    Then again, for a C-style array, *p++ accomplishes something very like a shift. Commented Jun 17, 2009 at 22:01
  • I should have mentioned this was a mutable array. Commented Jun 18, 2009 at 1:37

6 Answers 6

24

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.

Sign up to request clarification or add additional context in comments.

3 Comments

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.
The linked documentation says it behaves similarly to shift, sliding the other elements down.
If you really want a single method call, see my answer for a sample category declaration that adds what you need.
4

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.

2 Comments

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.
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.
2

It's certainly too late to assist the original poster, but if you have a plain NSArray and not an NSMutableArray, this works well:

id myData = myArray.firstObject;
myArray = [myArray subarrayWithRange:NSMakeRange(1, myArray.count - 1)];

1 Comment

Unless your array has only one item in it, in which case your loc value of 1 is outside that of the NSArray and you throw an NSRangeException
1

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.

1 Comment

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

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.

Comments

0

Use this code,

 [arrayName removeObjectAtIndex:0];

this may help you

1 Comment

This does not provide any additional useful information that the accepted answer did not already provide, and will only work in the case of an NSMutableArray (not NSArray)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.