Como remover um elemento de uma matriz no Swift

236

Como posso desmarcar / remover um elemento de uma matriz no novo idioma Swift da Apple?

Aqui está um código:

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

Como o elemento pode animals[2]ser removido da matriz?

Alegria Leopold
fonte

Respostas:

300

A letpalavra-chave é para declarar constantes que não podem ser alteradas. Se você deseja modificar uma variável, você deve usar var, por exemplo:

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

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

Uma alternativa não mutante que manterá a coleção original inalterada é usar filterpara criar uma nova coleção sem os elementos que você deseja remover, por exemplo:

let pets = animals.filter { $0 != "chimps" }
mythz
fonte
7
FYI: removeretorna o elemento removido:let animal = animals.remove(at: 2)
2Toad
1
podemos filtrar apenas com base no índice ??
shaqir saiyed 14/03/19
@shaqirsaiyed Você pode filtrar qualquer predicado que puder imaginar. por exemplo, você pode filtrar todos os animais que terminam em um "s".
Womble
adicionar animais = animais de estimação
Puji Wahono
197

Dado

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

Remova o primeiro elemento

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

Remover último elemento

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

Remover elemento no índice

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

Remover elemento de índice desconhecido

Para apenas um elemento

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

Para vários elementos

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

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

Notas

  • Os métodos acima modificam a matriz no local (exceto filter) e retornam o elemento que foi removido.
  • Guia Rápido para Reduzir o Filtro do Mapa
  • Se você não quiser modificar a matriz original, poderá usar dropFirstou dropLastcriar uma nova matriz.

Atualizado para o Swift 5.2

Suragch
fonte
Obrigado por estes exemplos, em Remover elemento de índice desconhecido > para vários elementos , que fechamento você escreveria para remover, chimps && moosepor exemplo? Estou procurando algo diferente do que:{$0 != "chimps" && $0 != "moose"}
161

As respostas acima parecem presumir que você conhece o índice do elemento que deseja excluir.

Muitas vezes, você conhece a referência ao objeto que deseja excluir na matriz. (Você iterou na sua matriz e a encontrou, por exemplo). Nesses casos, pode ser mais fácil trabalhar diretamente com a referência do objeto sem precisar passar em todo lugar seu índice. Por isso, sugiro esta solução. Ele usa o operador de identidade !== , usado para testar se duas referências a objetos se referem à mesma instância de objeto.

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

Claro que isso não funciona apenas para Strings.

Daniel
fonte
23
Deveria serlist = list.filter({ $0 != element })
Craig Grummitt 4/15
5
Não se você quiser verificar com o operador de identidade.
Daniel
3
array.indexOf({ $0 == obj })
CCI
2
Observe que se outros objetos fizerem referência a listessa exclusão não atualizarão as outras referências de matriz, pois você está atribuindo uma nova matriz list. Apenas uma implicação sutil se você excluir de matrizes com essa abordagem.
Crashalot 21/01
1
O paradigma de programação funcional depende de objetos imutáveis. Ou seja, você não os muda. Em vez disso, você cria um novo objeto. É isso que excluir, mapear, reduzir, etc. A lista será um objeto recém-criado. No snippet de código acima, estou atribuindo de volta à lista de um objeto recém-criado. Isso funciona para mim, porque eu desenvolvo meu código de uma maneira que segue a programação funcional.
Daniel
44

Swift 5: Aqui está uma extensão fácil e legal para remover elementos em uma matriz, sem filtrar:

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

}

Uso:

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

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

Também funciona com outros tipos, como Intsince Elementé um tipo genérico:

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

myArray.remove(object: objectToRemove) // [4, 8, 6, 2]
Skaal
fonte
1
Interessante, este array onde Elemento: parte Equatable
Nicolas Manzini
1
Brilhante. Embora ele não funciona se você começar com uma lista de protocolos, como - tipo de protocolo não pode conformar-se 'Equatable' porque somente tipos de concreto pode estar de acordo com protocolos :-(
AW101
22

Para Swift4:

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

fonte
15

A partir do Xcode 10+, e de acordo com a sessão 223 da WWDC 2018, "Abraçando algoritmos", um bom método daqui para frente serámutating func removeAll(where predicate: (Element) throws -> Bool) rethrows

Exemplo da 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."

consulte a documentação da Apple

Assim, no exemplo do OP, removendo animais [2], "chimps":

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

Esse método pode ser preferido porque ele escala bem (linear versus quadrático), é legível e limpo. Lembre-se de que ele só funciona no Xcode 10+ e, por escrito, isso está na versão beta.

davidrynn
fonte
removeAll (where :) será capaz apenas no veloz 4.2
Vlad Pulichev 4/18/18
14

Poucas operações estão relacionadas à matriz no Swift

Criar matriz

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

Adicionar objeto na matriz

stringArray = stringArray + ["Five"]

Obter valor do objeto Index

let x = stringArray[1]

Anexar Objeto

stringArray.append("At last position")

Inserir objeto no índice

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

Remover Objeto

stringArray.removeAtIndex(3)

Valor do objeto Concat

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

Você poderia fazer isso. Primeiro verifique se Dogrealmente existe na matriz e remova-a. Adicione a fordeclaração se você acredita que isso Dogpode acontecer mais de uma vez na sua matriz.

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

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

Se você tem certeza de que as Dogsaídas na matriz ocorreram apenas uma vez, faça isso:

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

Se você tiver ambos, strings e números

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)!)
        }
    }
}
GuiSoySauce
fonte
E se minha matriz não contiver Strings?
Apqu 30/06/16
@apqu fez outra atualização '|| objeto == Int () 'e' || objeto == String ()' são desnecessários
GuiSoySauce
o loop de uma matriz vai contra a eficiência. verifique .filter, .compactMap
MLBDG
10

Remova os elementos usando a matriz de índices:

  1. Matriz de strings e índices

    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. Matriz de números inteiros e índices

    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]



Remover elementos usando o valor do elemento de outra matriz

  1. Matrizes de números inteiros

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

    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"]
Krunal
fonte
4
Esta é uma resposta única e é muito eficiente para melhor codificação e execução rápida.
O iOSDev
Oi @Krunal - ótima resposta, você pode dar uma olhada na seguinte pergunta (liberando imagens de uma matriz de imagens): stackoverflow.com/questions/47735975/…
Server Programmer
6

Em relação à alternativa de @ Suragch para "Remover elemento de índice desconhecido":

Existe uma versão mais poderosa do "indexOf (elemento)" que corresponderá a um predicado em vez do próprio objeto. Ele tem o mesmo nome, mas é chamado por myObjects.indexOf {$ 0.property = valueToMatch}. Retorna o índice do primeiro item correspondente encontrado na matriz myObjects.

Se o elemento for um objeto / estrutura, convém remover esse elemento com base no valor de uma de suas propriedades. Por exemplo, você tem uma classe Car com a propriedade car.color e deseja remover o carro "vermelho" do carsArray.

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

Previsivelmente, você poderia refazer isso para remover "todos" os carros vermelhos incorporando a instrução if acima em um loop de repetição / while e anexando um bloco else para definir uma bandeira para "sair" do loop.

ObjectiveTC
fonte
6

Swift 5

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

Se você tiver uma matriz de objetos personalizados, poderá pesquisar por propriedade específica como esta:

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

ou se você deseja pesquisar por nome, por exemplo

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

Isso deve ser feito (não testado):

animals[2..3] = []

Edit: e você precisa torná-lo um var, não um let, caso contrário, é uma constante imutável.

Arquivo Analógico
fonte
5
Ao usar um (sub) intervalo de uma matriz existente para criar outra matriz, o intervalo precisa ter 3 pontos. O texto acima deve ser escrito como animal [2 ... 3]
zevij
3

Eu vim com a seguinte extensão que cuida da remoção de elementos de um Array, assumindo os elementos no Arrayimplemento Equatable:

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

}

Uso:

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

var test2 = [1, 2, 1, 2]
test2.removeFirstEqualItem(2) // [1, 1, 2]
nburk
fonte
Oi @ nburk - ótima resposta, você pode dar uma olhada na seguinte pergunta (liberando imagens de uma matriz de imagens): stackoverflow.com/questions/47735975/…
Server Programmer
1

extensão para remover o objeto String

extension Array {
    mutating func delete(element: String) {
        self = self.filter() { $0 as! String != element }
    }
}
Varun Naharia
fonte
força desembrulhar pode causar um acidente, acho que você deve evitá-lo neste caso.
precisa saber é o seguinte
O que é uma função "mutante"?
AwesomeElephant8232
costumava dizer que essa função mudará o self (array).
Varun Naharia
1

Eu uso essa extensão, quase a mesma da Varun, mas essa (abaixo) é para todos os fins:

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

Para remover elementos de uma matriz, use o remove(at:), removeLast()e removeAll().

yourArray = [1,2,3,4]

Remova o valor na posição 2

yourArray.remove(at: 2)

Remova o último valor da matriz

yourArray.removeLast()

Remove todos os membros do conjunto

yourArray.removeAll()
PatelFab
fonte