如何在for循环中安全地从数组中删除项目?

时间:2016-01-30 11:15:25

标签: arrays swift for-loop

完全透露,这是一个家庭作业问题:

  

它应该有[Circle]类型的私有属性。一系列圆圈。   该方法应删除任何半径大于的圆   最低要求,小于最高要求。

很明显,我应该使用removeAtIndex()来删除不符合循环中确定的条件的数组项。然而,许多人已经指出在循环中移除项目的危险之前,因为我猜是“迭代器/索引不匹配”。

最终我最终创建了一个空数组,并使用.append()将符合“良好”条件的值推送到filteredCircles数组,但我不禁感到这就是这个不符合转让标准。

是否有解决方案实际上在循环中从数组中删除了项目?

2 个答案:

答案 0 :(得分:11)

如果FOR LOOP 是强制性的(并且我在引用的文字中没有看到此要求),则应使用filter方法。

当您在数组上调用filter时,您会得到一个新数组,其中只包含与您传递给filter的闭包有关的值。 原始数组未发生变异。

struct Circle {
    let radius: Double
}

let circles = [Circle(radius: 1), Circle(radius: 5.1), Circle(radius: 4), Circle(radius: 10.8)]

let bigCircles = circles.filter { $0.radius > 5 }

为什么这种方法比在FOR LOOP中改变数组

更好
  1. 由于circles是常量,因此您不会遇到与多线程编程相关的问题。如果circles是可变的,那么其他线程可能会在您使用非常可怕的副作用进行循环时更改它。
  2. 不易出错。您没有编写CPU应该执行的操作,而是描述结果应该如何。所以你和编译器之间的误解可能会减少:)
  3. 您正在编写更少的代码,这意味着更少的潜在错误。
  4. 这些是编写函数式编程代码的一些好处。

答案 1 :(得分:1)

详细说明@ vacawama的答案:

struct Circle {
    var radius: Int
}

struct MyStruct {
    private var circles: [Circle]

    mutating func removeCirclesWithRadiusWithin(range: Range<Int>) {
        for index in (circles.startIndex..<circles.endIndex).reverse() {
            if range.contains(circles[index].radius) {
                circles.removeAtIndex(index)
            }
        }
    }
}

如果您想对Double Circle使用radius,但希望保留良好的语法:

struct Circle {
    var radius: Double
}

struct MyStruct {
    private var circles: [Circle]

    mutating func removeCirclesWithRadiusWithin<I: IntervalType where I.Bound == Double>(interval: I) {
        for index in (circles.startIndex..<circles.endIndex).reverse() {
            if interval.contains(circles[index].radius) {
                circles.removeAtIndex(index)
            }
        }
    }
}
相关问题