【问题标题】:How do I safely remove items from an array in a for loop?如何在 for 循环中安全地从数组中删除项目?
【发布时间】:2016-05-08 04:00:13
【问题描述】:

完全公开,这是一个家庭作业问题:

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

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

最终我创建了一个空数组并使用.append() 将满足“良好”条件的值推送到filteredCircles 数组,但我不禁觉得这不符合作业的标准。

有没有一种解决方案可以在循环中实际从数组中删除项目?

【问题讨论】:

  • 从最后一个索引开始循环,直到到达第一个。删除项目只会影响后面项目的索引。
  • @vacawama 如何在 Swift 中做到这一点?循环语法不允许索引——就像其他语言一样,所以我不知道如何倒数。
  • @vacawama Nm...刚刚了解了circles.enumerate().reverse()。谢谢!

标签: arrays swift for-loop


【解决方案1】:

如果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. 您正在编写更少的代码,这确实意味着更少的潜在错误。

这些是编写函数式编程代码的一些好处。

【讨论】:

  • 我想我应该尝试一下,但是.filter 是否真的修改了数组?
  • 没有。这就是为什么他将返回值分配给 circle 变量(必须使用 var 声明)
  • @nipponese:不,它没有。这是一件好事,因为(出于多种原因)circles 应该是一个常数。但是,如果您愿意,可以将 circle 设为 var 并将结果重新分配给同一个变量。
【解决方案2】:

在@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 用于您的Circleradius,但又想保持良好的语法:

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)
            }
        }
    }
}

【讨论】:

  • 因为您正在更改结构中存储属性的内容。因此,如果您使用let 声明了MyStruct 的实例,则无法使用此方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-19
  • 2021-05-21
  • 2021-12-25
相关资源
最近更新 更多