web-dev-qa-db-ja.com

forループ中に変更する配列のSwift 3にforループを書き込むにはどうすればよいですか?

したがって、次のような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
   }
}

カウントを再チェックせず、元のresults.countまで継続するため、配列IOOBE例外が発生します。

どうすれば修正できますか?現在は動作しますが、将来はトラブルに巻き込まれたくありません。

38

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の問題は、配列のインデックスを再作成しないことですin-place。したがって、countによる配列の境界外例外が発生します。更新されていません。

逆方向に走査することにより、境界外の例外を回避できます。

66
Unheilig

代わりにfilterを使用できますか?

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let greaterThan5 = numbers.filter{$0 >= 5}
print(greaterThan5)
17
Brandon Shega

for- loopを引き続き使用する場合は、enumerateを使用してインデックスと要素の両方を列挙できます。

for (index, element) in results.enumerate() {
   if (element < 5) {
     results.removeAtIndex(index)
   }
}

ループで何をしているのかにもよりますが、filterメソッドの方が良いかもしれません。

9
Luka Jacobowitz

ループが進む場合...

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

}
0
Miguel Herrero