Swiftの配列を列挙して、特定のアイテムを削除したいと思います。これが安全かどうか、そうでない場合はどうすればこれを達成できるのか疑問に思います。
現在、私はこれをやっているでしょう:
for (index, aString: String) in enumerate(array) {
//Some of the strings...
array.removeAtIndex(index)
}
回答:
スウィフト2では、これは使用して非常に簡単ですenumerate
とreverse
。
var a = [1,2,3,4,5,6]
for (i,num) in a.enumerate().reverse() {
a.removeAtIndex(i)
}
print(a)
filter
新しい配列を返します。アレイから何も削除していません。filter
列挙型とは呼ばないでしょう。猫の皮を剥ぐ方法は常に複数あります。
あなたはfilter
方法を考えるかもしれません:
var theStrings = ["foo", "bar", "zxy"]
// Filter only strings that begins with "b"
theStrings = theStrings.filter { $0.hasPrefix("b") }
のパラメータfilter
は、配列型インスタンス(この場合String
)を取り、を返す単なるクロージャですBool
。結果がtrue
要素を保持する場合、それ以外の場合、要素は除外されます。
filter
配列を更新せず、新しい配列を返すだけであることを明示します
filter
メソッドをmutating
1つにすることは可能ですか(mutating
キーワードを読んだので、self
代わりにこのような関数を変更できます)?
Array
mutating
でスウィフト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以降では、WWDC2018でAppleが推奨したより優れた高速な方法があります。
var c = ["a", "b", "c", "d", "e", "f"]
c.removeAll(where: {$0 == "c"})
print(c)
この新しい方法にはいくつかの利点があります。
filter
。{$0 === Class.self}
動作しません
特定のインデックスの要素が配列から削除されると、後続のすべての要素は1つの位置だけ戻るため、位置(およびインデックス)が変更されます。
したがって、最良の方法は、配列を逆の順序でナビゲートすることです。この場合、従来のforループを使用することをお勧めします。
for var index = array.count - 1; index >= 0; --index {
if condition {
array.removeAtIndex(index)
}
}
しかし、私の意見ではfilter
、@ perlflyが彼の回答で説明しているように、最善のアプローチはこの方法を使用することです。
いいえ、列挙中に配列を変更することは安全ではありません。コードがクラッシュします。
少数のオブジェクトのみを削除したい場合は、このfilter
機能を使用できます。
filter
が安全です。これが私のばかげた例です:var y = [1, 2, 3, 4, 5]; print(y); for (index, value) in y.enumerated() { y.remove(at: index) } print(y)
列挙中に要素をnilに設定し、完了後に配列filter()メソッドを使用してすべての空の要素を削除することをお勧めします。
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) // ["!", "@", "$"]