Подтвердить что ты не робот

Удалить определенный элемент массива, равный строке - Swift

Нет ли простого способа удалить определенный элемент из массива, если он равен заданной строке? Обходные пути - найти индекс элемента массива, который вы хотите удалить, а затем removeAtIndex или создать новый массив, в котором вы добавите все элементы, которые не равны данной строке. Но нет ли более быстрого пути?

4b9b3361

Ответ 1

Вы можете использовать filter() для фильтрации вашего массива следующим образом

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

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

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

редактировать/обновление:

Xcode 10 • Swift 4.2 или более поздняя версия

Вы можете использовать новый RangeReplaceableCollection мутирования RangeReplaceableCollection именем removeAll(where:)

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]"

Ответ 2

Не понятно, если быстрее вы имеете в виду время выполнения или количество кода.

В последнем случае вы можете легко создать копию, используя метод filter. Например, учитывая следующий массив:

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

вы можете создать копию со всеми элементами, кроме "2", как:

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

Ответ 3

Использование фильтра, как предложено выше, хорошо. Но если вы хотите удалить только одно вхождение значения или вы предполагаете, что в массиве нет дубликатов, и вам нужен более быстрый алгоритм, используйте это (в Swift3):

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

Ответ 4

Вы хотите использовать filter(). Если у вас есть один элемент (называемый say 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"
}

Ответ 5

Вы можете использовать filter() в сочетании с перегрузкой оператора для создания легко повторяемого решения:

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

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

myArrayOfStrings -= "Hello"

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

Ответ 6

если вам нужно удалить subArray из массива, это идеальное решение, используя Swift3:

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"]

это лучше для вашей производительности, а не для удаления по одному.

btw даже быстрее решение (но оно будет переупорядочивать элементы в конечном массиве):

array = Array(Set(array).subtracting(subArrayToDelete))