如何在Objective C中删除数组的第一个元素?

13

在 Objective C 中,是否有一种方法可以一行或者简短地移除(缩短一个)并返回一个数组的第一个元素,而不考虑它的索引位置?

在 Objective C 中,是否有一行代码或者其他简短的方式可以返回一个数组的第一个元素并且将其从数组中移除,而不需要考虑它的索引位置?

你是在谈论裸的C风格数组,还是类似于NSArray/NSMutableArray这样的东西? - Quinn Taylor
1
在裸的C风格数组的情况下,你在开始之前就会遇到麻烦:C风格数组不包括它们的边界/有效大小信息。我想你可以传递一个指向有效大小的指针,但那样会很丑陋... - Jeffrey Hantin
1
然而,对于 C 风格数组,*p++ 执行的类似于移位的操作。 - Jeffrey Hantin
我应该提到这是一个可变数组。 - ojreadmore
6个回答

24

我原本以为当我使用 removeObjectAtIndex:0 方法时,数组的索引会从1开始,就像在PHP中一样。但事实证明,将其删除(它是我添加到数组中最旧的元素)已足够满足我的需求。 - ojreadmore
1
链接的文档说明它的行为类似于 shift,将其他元素向下滑动。 - Jeffrey Hantin
如果你真的想要一个单一的方法调用,可以查看我的答案,其中包含一个示例类别声明,添加了你所需的内容。 - Quinn Taylor

4
那是一个糟糕的事情。
在iPhone上,Objective-C实际上可以使用C的大部分性能优势。
如果你看一下我的其他帖子,你会发现我非常反对过早优化,但是当你在C级别编码时,有些事情是不必要的。
- 移动内存 - 复制结构 - 分配稀疏填充的内存块 - 内部循环 - ...(还有很多,但是我的C生活已经有点生疏了,并且我反对优化)
你可能想要的是一个实现良好的队列。它预先分配一个足够大的循环内存结构,然后有两个指针跟踪第一个和最后一个字节。
如果Objective-C没有队列数据结构,那么我会非常惊讶。
此外,不要追求单行代码。所有关于简洁代码的东西都被高估了。如果调用一个方法更有意义,那就这样做。

Perl中的“数组”更像是一个良好实现的队列,而不是C数组;它们存储了指向“第一个”和“最后一个”元素的偏移量,并在需要时智能地预分配空间。 - ysth
更有理由在Objective-C中使用队列。大多数解释性语言比编译语言慢100倍左右,因此问题完全不同,所有数组都具有队列的开销是完全合理的,但在基于C的语言中找不到任何类似的东西。 - Bill K

2

虽然帮助原始作者已经太晚了,但如果你只有一个普通的NSArray而不是NSMutableArray,那么这个方法可以很好地解决问题:

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

除非你的数组只有一个项目,否则你的loc值为1将超出NSArray的范围,这时你需要抛出一个NSRangeException异常。 - SDJMcHattie

1

Cocoa数组对象(NSArray/NSMutableArray)没有提供一行等效的方法 - 您必须先读取对象,然后再删除它。这些类提供-lastObject-removeLastObject方法,但不提供-firstObject-removeFirstObject方法,这应该提醒您从数组前面删除通常是一种低效的操作,因为内容必须向前移动(复制)一个位置。对于C中的数组来说,这尤其如此,因为它们与指针密切相关。

如果您使用的是非原始数据类型和/或非常小的数组,那么您可能需要考虑到“移除”第一个元素的行为表明了一种队列数据结构。关于如何为对象创建队列的详细信息,请参见此 SO 问题。就我个人而言,对于这个问题,我的观点是真正的队列类提供了最清晰的编程习惯。您甚至可以定义自己的方法(可能作为NSMutableArray或另一个类别的一部分),提供一个一行代码来实现您想要的操作:
@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

然而,到那个时候,这个解决方案很可能会造成比它的价值更大的开销,这取决于您对使用它的代码的简单性与性能之间的重要性。

1
你的QueueOneLiner可能会返回一个无效的对象。removeObjectAtIndex:0将释放“对象”,如果不使用垃圾回收,可能会过早地释放它。在从数组中删除对象之前,您应该保留并自动释放该对象。 - dreamlax

1
如果你有一个数组 obj *arr,其中 obj 是一个类/类型名称,arr 是这个数组,你可以使用 arr+1 来获取除第一个元素外的整个数组。

0
请使用以下代码:
 [arrayName removeObjectAtIndex:0];

这可能会对你有所帮助


这并没有提供任何已被接受的答案未提供的额外有用信息,并且仅适用于NSMutableArray(而不是NSArray)的情况。 - Stonz2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接