[英]Removing from array during enumeration in Swift?
我想枚举Swift中的一个数组,并删除某些项目。 我想知道这样做是否安全,如果不安全,我应该如何实现这一目标。
目前,我会这样做:
for (index, aString: String) in enumerate(array) {
//Some of the strings...
array.removeAtIndex(index)
}
在 Swift 2 中,这很容易使用enumerate
和reverse
。
var a = [1,2,3,4,5,6]
for (i,num) in a.enumerate().reverse() {
a.removeAtIndex(i)
}
print(a)
您可能会考虑filter
方式:
var theStrings = ["foo", "bar", "zxy"]
// Filter only strings that begins with "b"
theStrings = theStrings.filter { $0.hasPrefix("b") }
filter
的参数只是一个闭包,它接受一个数组类型实例(在本例中为String
)并返回一个Bool
。 当结果为true
它保留该元素,否则该元素被过滤掉。
在Swift 3 和 4 中,这将是:
用数字,根据约翰斯顿的回答:
var a = [1,2,3,4,5,6]
for (i,num) in a.enumerated().reversed() {
a.remove(at: i)
}
print(a)
用字符串作为 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)
但是,现在在 Swift 4.2 或更高版本中, Apple 在 WWDC2018 中推荐了一种更好、更快的方法:
var c = ["a", "b", "c", "d", "e", "f"]
c.removeAll(where: {$0 == "c"})
print(c)
这种新方式有几个优点:
filter
实现更快。当某个索引处的元素从数组中移除时,所有后续元素的位置(和索引)都将发生变化,因为它们向后移动了一个位置。
所以最好的方法是以相反的顺序导航数组 - 在这种情况下,我建议使用传统的 for 循环:
for var index = array.count - 1; index >= 0; --index {
if condition {
array.removeAtIndex(index)
}
}
然而,在我看来,最好的方法是使用filter
方法,正如@perlfly 在他的回答中所描述的那样。
不,在枚举期间改变数组是不安全的,你的代码会崩溃。
如果您只想删除几个对象,您可以使用filter
功能。
要么创建一个可变数组来存储要删除的项目,然后在枚举之后,从原始项目中删除这些项目。 或者,创建数组的副本(不可变),枚举它并在枚举时从原始对象中删除对象(而不是通过索引)。
传统的 for 循环可以用一个简单的 while 循环代替,如果您还需要在删除之前对每个元素执行一些其他操作,这将非常有用。
var index = array.count-1
while index >= 0 {
let element = array[index]
//any operations on element
array.remove(at: index)
index -= 1
}
我建议在枚举期间将元素设置为 nil,并在完成后使用数组 filter() 方法删除所有空元素。
补充一点,如果您有多个数组,并且数组 A 的索引 N 中的每个元素都与数组 B 的索引 N 相关,那么您仍然可以使用反转枚举数组的方法(如过去的答案)。 但请记住,在访问和删除其他数组的元素时,无需反转它们。
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) // ["!", "@", "$"]
你可以这样做Swift 5
arr?.removeAll(where: {$0.id as! Int == id})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.