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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28323848/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:40:14  来源:igfitidea点击:

Removing from array during enumeration in Swift?

iosarraysswiftenumeration

提问by Andrew

I want to enumerate through an array in Swift, and remove certain items. I'm wondering if this is safe to do, and if not, how I'm supposed to achieve this.

我想在 Swift 中枚举一个数组,并删除某些项目。我想知道这样做是否安全,如果不是,我应该如何实现这一目标。

Currently, I'd be doing this:

目前,我会这样做:

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

回答by Johnston

In Swift 2 this is quite easy using enumerateand reverse.

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

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

回答by Matteo Piombo

You might consider filterway:

你可以考虑的filter方式:

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

// Filter only strings that begins with "b"
theStrings = theStrings.filter { 
var a = [1,2,3,4,5,6]
for (i,num) in a.enumerated().reversed() {
   a.remove(at: i)
}
print(a)
.hasPrefix("b") }

The parameter of filteris just a closure that takes an array type instance (in this case String) and returns a Bool. When the result is trueit keeps the element, otherwise the element is filtered out.

的参数filter只是一个闭包,它接受一个数组类型实例(在本例中为String)并返回一个Bool。当结果是true它保留元素,否则元素被过滤掉。

回答by jvarela

In Swift 3 and 4, this would be:

Swift 3 和 4 中,这将是:

With numbers, according to Johnston's answer:

用数字,根据约翰斯顿的回答:

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

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

With stringsas the OP's question:

字符串作为 OP 的问题:

var c = ["a", "b", "c", "d", "e", "f"]
c.removeAll(where: {
for var index = array.count - 1; index >= 0; --index {
    if condition {
        array.removeAtIndex(index)
    }
}
== "c"}) print(c)

However, now in Swift 4.2 or later, there is even a better, faster waythat was recommended by Apple in WWDC2018:

但是,现在在 Swift 4.2 或更高版本中,Apple 在 WWDC2018 中推荐了一种更好、更快的方法

var index = array.count-1
while index >= 0 {

     let element = array[index]
     //any operations on element
     array.remove(at: index)

     index -= 1
}

This new way has several advantages:

这种新方式有几个优点:

  1. It is faster than implementations with filter.
  2. It does away with the need of reversing arrays.
  3. It removes items in-place, and thus it updates the original array instead of allocating and returning a new array.
  1. 它比使用filter.
  2. 它不需要反转数组。
  3. 它就地删除项目,因此它更新原始数组而不是分配和返回新数组。

回答by Antonio

When an element at a certain index is removed from an array, all subsequent elements will have their position (and index) changed, because they shift back by one position.

当某个索引处的元素从数组中移除时,所有后续元素的位置(和索引)都将发生变化,因为它们向后移动了一个位置。

So the best way is to navigate the array in reverse order - and in this case I suggest using a traditional for loop:

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

Like so, (one can copy and paste this on Playground)

var a = ["a", "b", "c", "d"]
var b = [1, 2, 3, 4]
var c = ["!", "@", "#", "$"]

// remove c, 3, #

for (index, ch) in a.enumerated().reversed() {
    print("CH: \(ch). INDEX: \(index) | b: \(b[index]) | c: \(c[index])")
    if ch == "c" {
        a.remove(at: index)
        b.remove(at: index)
        c.remove(at: index)
    }
}

print("-----")
print(a) // ["a", "b", "d"]
print(b) // [1, 2, 4]
print(c) // ["!", "@", "$"]

However in my opinion the best approach is by using the filtermethod, as described by @perlfly in his answer.

但是,在我看来,最好的方法是使用该filter方法,正如@perlfly 在他的回答中所描述的那样。

回答by Starscream

No it's not safe to mutate arrays during enumaration, your code will crash.

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

If you want to delete only a few objects you can use the filterfunction.

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

回答by Locutus

The traditional for loop could be replaced with a simple while loop, useful if you also need to perform some other operations on each element prior to removal.

传统的 for 循环可以用一个简单的 while 循环代替,如果您还需要在删除之前对每个元素执行一些其他操作,这将非常有用。

##代码##

回答by Wain

Either create a mutable array to store the items to be deleted and then, after the enumeration, remove those items from the original. Or, create a copy of the array (immutable), enumerate that and remove the objects (not by index) from the original while enumerating.

要么创建一个可变数组来存储要删除的项目,然后在枚举之后,从原始项目中删除这些项目。或者,创建数组的副本(不可变),枚举它并在枚举时从原始对象中删除对象(而不是通过索引)。

回答by freele

I recommend to set elements to nil during enumeration, and after completing remove all empty elements using arrays filter() method.

我建议在枚举期间将元素设置为 nil,并在完成后使用数组 filter() 方法删除所有空元素。

回答by Glenn

Just to add, if you have multiple arrays and each element in index N of array A is related to the index N of array B, then you can still use the method reversing the enumerated array (like the past answers). But remember that when accessing and deleting the elements of the other arrays, no need to reverse them.

补充一点,如果您有多个数组,并且数组 A 的索引 N 中的每个元素都与数组 B 的索引 N 相关,那么您仍然可以使用反转枚举数组的方法(如过去的答案)。但请记住,在访问和删除其他数组的元素时,无需反转它们。

##代码##