Swiftで配列から要素を削除する方法


236

Appleの新しい言語Swiftの配列から要素を設定解除/削除するにはどうすればよいですか?

ここにいくつかのコードがあります:

let animals = ["cats", "dogs", "chimps", "moose"]

要素をanimals[2]配列から削除するにはどうすればよいですか?

回答:


300

letキーワードを変更することはできません定数を宣言するためです。変数を変更する場合は、var代わりに使用する必要があります。例:

var animals = ["cats", "dogs", "chimps", "moose"]

animals.remove(at: 2)  //["cats", "dogs", "moose"]

元のコレクションを変更せずに維持するための非変異型の代替方法は、filter削除する要素なしで新しいコレクションを作成するために使用することです。例:

let pets = animals.filter { $0 != "chimps" }

7
FYI:remove削除された要素を返します:let animal = animals.remove(at: 2)
2Toad

1
インデックスのみに基づいてフィルタリングできますか?
shaqirが

@shaqirsaiyed考えることができる任意の述語でフィルタリングできます。たとえば、「s」で終わるすべての動物を除外できます。
Womble

動物を追加する=ペット
Puji Wahono

197

与えられた

var animals = ["cats", "dogs", "chimps", "moose"]

最初の要素を削除

animals.removeFirst() // "cats"
print(animals)        // ["dogs", "chimps", "moose"]

最後の要素を削除

animals.removeLast() // "moose"
print(animals)       // ["cats", "dogs", "chimps"]

インデックスの要素を削除

animals.remove(at: 2) // "chimps"
print(animals)           // ["cats", "dogs", "moose"]

不明なインデックスの要素を削除

1つの要素のみ

if let index = animals.firstIndex(of: "chimps") {
    animals.remove(at: index)
}
print(animals) // ["cats", "dogs", "moose"]

複数の要素の場合

var animals = ["cats", "dogs", "chimps", "moose", "chimps"]

animals = animals.filter(){$0 != "chimps"}
print(animals) // ["cats", "dogs", "moose"]

ノート

  • 上記のメソッドは、配列を所定の位置に変更し(を除くfilter)、削除された要素を返します。
  • Map Filter ReduceのSwiftガイド
  • 元の配列を変更したくない場合は、dropFirstまたはdropLastを使用して新しい配列を作成できます。

Swift 5.2に更新


これらの例のおかげで、不明なインデックスの要素削除する > 複数の要素のchimps && moose場合、たとえば、どのクロージャーを削除して削除しますか?私はそれとは異なるものを探しています{$0 != "chimps" && $0 != "moose"}

161

上記の回答は、削除する要素のインデックスがわかっていることを前提としているようです。

多くの場合、配列内で削除するオブジェクトへの参照を知っています。(たとえば、配列を反復処理してそれを見つけた場合など)このような場合、インデックスをどこにも渡さなくても、オブジェクト参照を直接操作する方が簡単な場合があります。したがって、私はこの解決策を提案します。これは、2つのオブジェクト参照が両方とも同じオブジェクトインスタンスを参照しているかどうかをテストするために使用するID演算子 !==を使用します。

func delete(element: String) {
    list = list.filter() { $0 !== element }
}

もちろん、これはStrings だけでは機能しません。


23
する必要がありますlist = list.filter({ $0 != element })
クレイググラミット2015

5
アイデンティティ演算子で確認したい場合はそうではありません。
Daniel

3
array.indexOf({ $0 == obj })
jrc

2
list新しい配列を割り当てているため、他のオブジェクトがこの削除を参照しても、他の配列参照は更新されないことに注意してくださいlist。この方法で配列から削除した場合、ほんのわずかな影響があります。
Crashalot 2016年

1
関数型プログラミングのパラダイムは、不変オブジェクトに依存しています。つまり、それらを変更しません。代わりに、新しいオブジェクトを作成します。これは、削除、マッピング、削減などの機能です。リストは新しく作成されたオブジェクトになります。上記のコードスニペットでは、新しく作成したオブジェクトをリストするために割り当て直しています。関数型プログラミングに従ってコードを設計しているので、これは私にとってはうまくいきます。
ダニエル

44

Swift 5:これ は、フィルタリングせずに配列内の要素を削除するためのクールで簡単な拡張機能です。

   extension Array where Element: Equatable {

    // Remove first collection element that is equal to the given `object`:
    mutating func remove(object: Element) {
        guard let index = firstIndex(of: object) else {return}
        remove(at: index)
    }

}

使用法 :

var myArray = ["cat", "barbecue", "pancake", "frog"]
let objectToRemove = "cat"

myArray.remove(object: objectToRemove) // ["barbecue", "pancake", "frog"]

ジェネリック型であるIntため、他の型とも連携しますElement

var myArray = [4, 8, 17, 6, 2]
let objectToRemove = 17

myArray.remove(object: objectToRemove) // [4, 8, 6, 2]

1
Equatable一部:この配列要素面白い
ニコラ・マンジニ

1
鮮やかさ。次のように、プロトコルのリストから始めた場合は機能しませんが、プロトコルタイプは「Equatable」に準拠できません。具体的なタイプのみがプロトコルに準拠できるためです:-(
AW101

22

Swift4の場合:

list = list.filter{$0 != "your Value"}

15

Xcode 10+以降、およびWWDC 2018セッション223「Embracing Algorithms」によると、今後の良い方法はmutating func removeAll(where predicate: (Element) throws -> Bool) rethrows

Appleの例:

var phrase = "The rain in Spain stays mainly in the plain."
let vowels: Set<Character> = ["a", "e", "i", "o", "u"]

phrase.removeAll(where: { vowels.contains($0) })
// phrase == "Th rn n Spn stys mnly n th pln."

Appleのドキュメントを参照

OPの例では、動物を削除します[2]、「チンパンジー」:

var animals = ["cats", "dogs", "chimps", "moose"]
animals.removeAll(where: { $0 == "chimps" } )
// or animals.removeAll { $0 == "chimps" }

この方法は、スケーリングがよく(線形対2次)、読み取り可能でクリーンであるため、推奨される方法です。これはXcode 10以降でのみ機能し、執筆時点ではベータ版です。


removeAll(where :)は
Swift

14

Swiftの配列に関連する操作はほとんどありません

アレイを作成

var stringArray = ["One", "Two", "Three", "Four"]

配列にオブジェクトを追加

stringArray = stringArray + ["Five"]

Indexオブジェクトから値を取得

let x = stringArray[1]

オブジェクトを追加

stringArray.append("At last position")

インデックスにオブジェクトを挿入

stringArray.insert("Going", atIndex: 1)

オブジェクトを削除

stringArray.removeAtIndex(3)

連結オブジェクト値

var string = "Concate Two object of Array \(stringArray[1]) + \(stringArray[2])"

14

あなたはそれを行うことができます。最初にDog本当に配列に存在することを確認してから、それを削除します。アレイで複数回発生する可能性があるforと思わDogれる場合は、ステートメントを追加してください。

var animals = ["Dog", "Cat", "Mouse", "Dog"]
let animalToRemove = "Dog"

for object in animals
{
    if object == animalToRemove{
        animals.removeAtIndex(animals.indexOf(animalToRemove)!)
    }
}

確かにDog配列に存在し、一度だけ発生した場合は、次のようにします。

animals.removeAtIndex(animals.indexOf(animalToRemove)!)

文字列と数値の両方がある場合

var array = [12, 23, "Dog", 78, 23]
let numberToRemove = 23
let animalToRemove = "Dog"

for object in array
{

    if object is Int
    {
        // this will deal with integer. You can change to Float, Bool, etc...
        if object == numberToRemove
        {
        array.removeAtIndex(array.indexOf(numberToRemove)!)
        }
    }
    if object is String
    {
        // this will deal with strings
        if object == animalToRemove
        {
        array.removeAtIndex(array.indexOf(animalToRemove)!)
        }
    }
}

配列に文字列が含まれていない場合はどうなりますか?
2016年

@apquが別の更新を行いました '|| オブジェクト== Int() 'および' || object == String() 'は不要
GuiSoySauce

配列をループすると効率が向上します。.filter、.compactMapをチェック
MLBDG 2018


10

インデックス配列を使用して要素を削除します。

  1. 文字列とインデックスの配列

    let animals = ["cats", "dogs", "chimps", "moose", "squarrel", "cow"]
    let indexAnimals = [0, 3, 4]
    let arrayRemainingAnimals = animals
        .enumerated()
        .filter { !indexAnimals.contains($0.offset) }
        .map { $0.element }
    
    print(arrayRemainingAnimals)
    
    //result - ["dogs", "chimps", "cow"]
  2. 整数とインデックスの配列

    var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
    let indexesToRemove = [3, 5, 8, 12]
    
    numbers = numbers
        .enumerated()
        .filter { !indexesToRemove.contains($0.offset) }
        .map { $0.element }
    
    print(numbers)
    
    //result - [0, 1, 2, 4, 6, 7, 9, 10, 11]



別の配列の要素値を使用して要素を削除します

  1. 整数の配列

    let arrayResult = numbers.filter { element in
        return !indexesToRemove.contains(element)
    }
    print(arrayResult)
    
    //result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
  2. 文字列の配列

    let arrayLetters = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
    let arrayRemoveLetters = ["a", "e", "g", "h"]
    let arrayRemainingLetters = arrayLetters.filter {
        !arrayRemoveLetters.contains($0)
    }
    
    print(arrayRemainingLetters)
    
    //result - ["b", "c", "d", "f", "i"]

4
これは1つの重要な答えであり、より良いコーディングと高速実行のために非常に効率的です。
iOSDev 2017年

: -こんにちは@Krunal偉大な答えは、あなたが(画像アレイからの画像を解放する)、次の質問を見てみることができstackoverflow.com/questions/47735975/...
Serverプログラマー

6

「不明なインデックスの要素を削除」するための@Suragchの代替案について:

オブジェクト自体ではなく述語で一致する「indexOf(element)」のより強力なバージョンがあります。名前は同じですが、myObjects.indexOf {$ 0.property = valueToMatch}によって呼び出されます。myObjects配列で最初に見つかった項目のインデックスを返します。

要素がオブジェクト/構造体の場合、そのプロパティのいずれかの値に基づいてその要素を削除することができます。たとえば、car.colorプロパティを持つCarクラスがあり、carsArrayから「赤い」車を削除するとします。

if let validIndex = (carsArray.indexOf{$0.color == UIColor.redColor()}) {
  carsArray.removeAtIndex(validIndex)
}

おそらく、これをやり直して、上記のifステートメントをrepeat / whileループ内に埋め込み、elseブロックを追加してフラグをループから「ブレーク」するように設定することで、「すべての」赤い車を削除できます。


6

スウィフト5

guard let index = orders.firstIndex(of: videoID) else { return }
orders.remove(at: index)

4

カスタムオブジェクトの配列がある場合は、次のような特定のプロパティで検索できます。

    if let index = doctorsInArea.indexOf({$0.id == doctor.id}){
        doctorsInArea.removeAtIndex(index)
    }

または、たとえば名前で検索したい場合

    if let index = doctorsInArea.indexOf({$0.name == doctor.name}){
        doctorsInArea.removeAtIndex(index)
    }

3

これはそれを行うはずです(テストされていません):

animals[2..3] = []

編集:そして、あなたはそれをa varではなくにする必要がありますlet、そうでなければそれは不変の定数です。


5
既存の配列の(サブ)範囲を使用して別の配列を作成する場合、範囲には3つのドットが必要です。上記は動物として書く必要があります[2 ... 3]
zevij

3

実装Array内の要素を想定して、から要素を削除する次の拡張機能を思いつきました。ArrayEquatable

extension Array where Element: Equatable {

  mutating func removeEqualItems(item: Element) {
    self = self.filter { (currentItem: Element) -> Bool in
      return currentItem != item
    }
  }

  mutating func removeFirstEqualItem(item: Element) {
    guard var currentItem = self.first else { return }
    var index = 0
    while currentItem != item {
      index += 1
      currentItem = self[index]
    }
    self.removeAtIndex(index)
  }

}

使用法:

var test1 = [1, 2, 1, 2]
test1.removeEqualItems(2) // [1, 1]

var test2 = [1, 2, 1, 2]
test2.removeFirstEqualItem(2) // [1, 1, 2]

: - @nburkこんにちは偉大な答えは、あなたは、次の質問を見てかかることがあります(画像アレイからの画像を解放する)stackoverflow.com/questions/47735975/...
Serverプログラマー

1

Stringオブジェクトを削除する拡張機能

extension Array {
    mutating func delete(element: String) {
        self = self.filter() { $0 as! String != element }
    }
}

強制アンラップはクラッシュを引き起こす可能性があるので、この場合は回避する必要があります。
user3206558 2017

「変化する」関数とは何ですか?
AwesomeElephant8232

以前は、この関数がself(array)を変更すると言っていました。
Varun Naharia

1

私はこの拡張を使用します。これはVarunの拡張とほとんど同じですが、この拡張(下記)は多目的です。

 extension Array where Element: Equatable  {
        mutating func delete(element: Iterator.Element) {
                self = self.filter{$0 != element }
        }
    }

1

配列から要素を削除するにはremove(at:)removeLast()とを使用しremoveAll()ます。

yourArray = [1,2,3,4]

2桁の値を削除

yourArray.remove(at: 2)

配列から最後の値を削除します

yourArray.removeLast()

セットからすべてのメンバーを削除します

yourArray.removeAll()
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.