Как написать цикл for в Swift 3 для массива, который я изменяю во время цикла for?
Автор вопроса: QuantumHoneybeesОтветов: 4
Итак, у меня есть цикл for, который выглядит примерно так:
for var i = 0; i < results.count ; i += 1 {
if (results[i] < 5) {
results.removeAtIndex(i)
i -= 1
}
}
Раньше это работало. Но когда я изменил его на предпочитаемый синтаксис Swift 3.0:
for var i in 0..<results.count {
if (results[i] < 5) {
results.removeAtIndex(i)
i -= 1
}
}
Я получаю исключение массива IOOBE, потому что он не перепроверяет счетчик и продолжается до исходного results.count.
Как это исправить? Сейчас это работает, но я не хочу попасть в беду в будущем.
этот код не жалуется на var i в 0..‹results.count { if (results[i] ‹ 5) { results.removeAtIndex(i) i -= 1 } } Amr Angry 19.02.2017
не имеет смысла, почему Apple сделала цикл for таким сложным, я никогда не помню, чтобы у меня были проблемы с ним за последние 25 лет. Klajd Deda 20.10.2017
Хотя решение, использующее filter, является прекрасным решением и более Swift-ly, есть и другой способ, если использование for-in все же желательно:
var results = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for var i in (0..<results.count).reverse()
{
if (results[i] < 5)
{
results.removeAtIndex(i)
//i -= 1
}
}
print(results)
Результат:
[5, 6, 7, 8, 9, 10]
Кроме того, мы могли бы вообще опустить эту строку i -= 1.
Проблема с removeAtIndex в цикле заключается в том, что он не приведет к переиндексации массива на месте и, таким образом, вызовет исключение массива за пределами границ из-за того, что count не обновляется.
Таким образом, перемещаясь назад, можно избежать исключения за пределами границ.
Ответ 2 · рейтинг 17 · Brandon Shega
Не могли бы вы использовать filter вместо этого?
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let greaterThan5 = numbers.filter{$0 >= 5}
print(greaterThan5)
Ответ 3 · рейтинг 12 · Luka Jacobowitz
Если вы хотите продолжить использовать цикл for, вы можете перечислить как индекс, так и элемент, используя enumerate:
for (index, element) in results.enumerate() {
if (element < 5) {
results.removeAtIndex(index)
}
}
Хотя в зависимости от того, что вы делаете в своем цикле, метод filter может быть лучшей идеей.
Ответ 4 · Miguel Herrero
Если ваша петля идет вперед...
for var i in (0..<results.count) where results.indices.contains(i) {
//if the index doesn't exist, the loop will be stopped.
if (results[i] < 5) {
results.removeAtIndex(i)
}
}