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?

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

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


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.


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]

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

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.


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

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

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

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.


6

Swift 5

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

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

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.


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]

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

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

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()
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.