在Swift中枚举期间从数组中删除?

And*_*rew 77 arrays enumeration ios swift

我想枚举Swift中的数组,并删除某些项目.我想知道这是否安全,如果没有,我应该如何做到这一点.

目前,我会这样做:

for (index, aString: String) in enumerate(array) {
    //Some of the strings...
    array.removeAtIndex(index)
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*ton 63

在Swift 2中,这很容易使用enumeratereverse.

var a = [1,2,3,4,5,6]
for (i,num) in a.enumerate().reverse() {
    a.removeAtIndex(i)
}
print(a)
Run Code Online (Sandbox Code Playgroud)

在这里查看我的swiftstub:http://swiftstub.com/944024718/?v = beta

  • @Mayerz False."我希望**通过Swift中的数组枚举**,并删除某些项目." `filter`返回一个新数组.您没有从阵列中删除任何内容.我甚至不会将`filter`称为枚举.皮肤猫总有不止一种方法. (12认同)
  • 严厉,我的坏!Pla不会给任何猫皮肤 (5认同)
  • 有效,但过滤器确实是要走的路 (2认同)

Mat*_*mbo 55

你可能会考虑filter:

var theStrings = ["foo", "bar", "zxy"]

// Filter only strings that begins with "b"
theStrings = theStrings.filter { $0.hasPrefix("b") }
Run Code Online (Sandbox Code Playgroud)

参数filter只是一个闭包,它接受一个数组类型实例(在这种情况下String)并返回一个Bool.结果是true保留元素,否则元素被过滤掉.

  • 我明确指出`filter`不会更新数组,只返回一个新数组 (14认同)

jva*_*ela 33

Swift 3和4中,这将是:

根据约翰斯顿的答案,有了数字:

var a = [1,2,3,4,5,6]
for (i,num) in a.enumerated().reversed() {
   a.remove(at: i)
}
print(a)
Run Code Online (Sandbox Code Playgroud)

使用字符串作为OP的问题:

var b = ["a", "b", "c", "d", "e", "f"]

for (i,str) in b.enumerated().reversed()
{
    if str == "c"
    {
        b.remove(at: i)
    }
}
print(b)
Run Code Online (Sandbox Code Playgroud)

但是,现在在Swift 4.2中, Apple 甚至在WWDC2018中推荐了一种更好,更快的方式:

var c = ["a", "b", "c", "d", "e", "f"]
c.removeAll(where: {$0 == "c"})
print(c)
Run Code Online (Sandbox Code Playgroud)

这种新方式有几个优点:

  1. 它比实现更快filter.
  2. 它不需要反转阵列.
  3. 它就地删除了项目,因此它更新了原始数组,而不是分配和返回一个新数组.


Ant*_*nio 13

当从数组中删除某个索引处的元素时,所有后续元素的位置(和索引)都会更改,因为它们会向后移动一个位置.

所以最好的方法是以相反的顺序导航数组 - 在这种情况下,我建议使用传统的for循环:

for var index = array.count - 1; index >= 0; --index {
    if condition {
        array.removeAtIndex(index)
    }
}
Run Code Online (Sandbox Code Playgroud)

但是在我看来,最好的方法是使用filter@perlfly在他的回答中描述的方法.


Sta*_*eam 5

不,在枚举期间改变数组是不安全的,您的代码会崩溃。

如果您只想删除几个对象,可以使用该filter功能。

  • 这对于 Swift 来说是不正确的。数组是**值**类型,因此当它们传递给函数、分配给变量或在枚举中使用时,它们会被“复制”。(Swift 为值类型实现了写时复制功能,因此实际复制量保持在最低限度。)尝试以下方法进行验证: var x = [1, 2, 3, 4, 5]; 打印(x);变量我 = 0; for v in x { if (v % 2 == 0) { x.remove(at: i) } else { i += 1 } }; 打印(x) (3认同)