web-dev-qa-db-ja.com

文字列に等しい特定の配列要素を削除-Swift

特定の要素が特定の文字列と等しい場合、配列から特定の要素を削除する簡単な方法はありませんか?回避策は、削除したい配列の要素のインデックスを見つけてremoveAtIndexにするか、指定した文字列と等しくないすべての要素を追加する新しい配列を作成することです。しかし、より速い方法はありませんか?

52
TimWhiting

filter()を使用して、次のように配列をフィルタリングできます

_var strings = ["Hello","Playground","World"]

strings = strings.filter{$0 != "Hello"}

print(strings)   // "[Playground, World]"
_

編集/更新:

Xcode 10•Swift 4.2以降

removeAll(where:)と呼ばれる新しいRangeReplaceableCollection変更メソッドを使用できます

_var strings = ["Hello","Playground","World"]

strings.removeAll { $0 == "Hello" }

print(strings)   // "[Playground, World]"
_

要素の最初の出現のみを削除する必要がある場合は、RangeReplaceableCollectionでカスタム削除メソッドを実装して、要素をEquatableに制約します。

_extension RangeReplaceableCollection where Element: Equatable {
    @discardableResult
    mutating func removeFirstElementEqual(to element: Element) -> Element? {
        guard let index = firstIndex(of: element) else { return nil }
        return remove(at: index)
    }
}
_

または、赤道以外の要素に述語を使用します。

_extension RangeReplaceableCollection {
    @discardableResult
    mutating func removeFirstElement(where predicate:  @escaping ((Element) -> Bool)) -> Element? {
        guard let index = firstIndex(where: predicate) else { return nil }
        return remove(at: index)
    }
}
_

_var strings = ["Hello","Playground","World"]
strings.removeFirstElementEqual(to: "Hello")
print(strings)   // "[Playground, World]"
strings.removeFirstElement { $0 == "Playground" }
print(strings)   // "[World]"
_
126
Leo Dabus

上記のようなフィルターを使用するのはいいことです。ただし、値の1つのオカレンスのみを削除する場合、または配列内に重複がないと仮定し、より高速なアルゴリズムが必要な場合は、これを使用します(Swift3で)。

if let index = array.index(of: "stringToRemove") {
    array.remove(at: index)
} else {
    // not found
}
9

実行時間またはコードの量の観点で、より速く意味するかどうかは明確ではありません。

後者の場合、filterメソッドを使用して簡単にコピーを作成できます。たとえば、次の配列があるとします:

let array = ["1", "2", "3", "4", "5"]

次のように、「2」以外のすべての要素を含むコピーを作成できます。

let filteredArray = array.filter { $0 != "2" }
9
Antonio

filter()を使用します。削除する単一の要素(たとえばobjと呼ばれる)がある場合、filter()述部は{ $0 != obj }。大きなアレイに対してこれを繰り返し行うと、パフォーマンスの問題になる可能性があります。個々のオブジェクトの削除を延期でき、サブ配列全体を削除する場合は、次のようなものを使用します。

var stringsToRemove : [String] = ...
var strings : [String] = ...

strings.filter { !contains(stringsToRemove, $0) }

例えば:

 1> ["a", "b", "c", "d"].filter { !contains(["b", "c"], $0) }
$R5: [String] = 2 values {
  [0] = "a"
  [1] = "d"
}
7
GoZoner

filter()を演算子のオーバーロードと組み合わせて使用​​すると、簡単に再現可能なソリューションを作成できます

func -= (inout left: [String], right: String){
    left = left.filter{$0 != right}    
}

var myArrayOfStrings:[String] = ["Hello","Playground","World"]

myArrayOfStrings -= "Hello"

print(myArrayOfStrings)   // "[Playground, World]"
4
tukbuk23

配列からsubArrayを削除する必要がある場合、これはSwiftを使用した完璧なソリューションです。

var array = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]            
let subArrayToDelete = ["c", "d", "e", "ee"]
array = array.filter{ !subArrayToDelete.contains($0) }
print(array) // ["a", "b", "f", "g", "h", "i", "j"]

これは、1つずつ削除するよりもパフォーマンスに優れています。

btw even faster solution is(しかし、最終配列のアイテムを再配置します):

array = Array(Set(array).subtracting(subArrayToDelete))
2
Tung Fam