Cómo eliminar un elemento de una matriz en Swift


236

¿Cómo puedo desarmar / eliminar un elemento de una matriz en el nuevo lenguaje Swift de Apple?

Aquí hay un código:

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

¿Cómo podría animals[2]eliminarse el elemento de la matriz?

Respuestas:


300

La letpalabra clave es para declarar constantes que no se pueden cambiar. Si desea modificar una variable, debe usarla var, por ejemplo:

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

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

Una alternativa no mutante que mantendrá la colección original sin cambios es usarla filterpara crear una nueva colección sin los elementos que desea eliminar, por ejemplo:

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

77
FYI: removedevuelve el elemento eliminado:let animal = animals.remove(at: 2)
2Toad

1
¿podemos filtrar solo en función del índice?
Shaqir dijo el

@shaqirsaiyed Puedes filtrar cualquier predicado que puedas imaginar. por ejemplo, puede filtrar todos los animales que terminan en una "s".
Womble

agregar animales = mascotas
Puji Wahono

197

Dado

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

Eliminar primer elemento

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

Eliminar el último elemento

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

Eliminar elemento en el índice

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

Eliminar elemento de índice desconocido

Para un solo elemento

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

Para elementos múltiples

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

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

Notas

  • Los métodos anteriores modifican la matriz en su lugar (excepto filter) y devuelven el elemento que se eliminó.
  • Guía rápida para reducir el filtro del mapa
  • Si no desea modificar la matriz original, puede usar dropFirsto dropLastcrear una nueva matriz.

Actualizado a Swift 5.2


Gracias por estos ejemplos, en Eliminar elemento de índice desconocido > para varios elementos , ¿qué cierre escribiría para eliminar, chimps && moosepor ejemplo? Estoy buscando algo diferente a{$0 != "chimps" && $0 != "moose"}

161

Las respuestas anteriores parecen suponer que conoce el índice del elemento que desea eliminar.

A menudo conoce la referencia al objeto que desea eliminar en la matriz. (Recorriste tu matriz y la encontraste, por ejemplo). En tales casos, podría ser más fácil trabajar directamente con la referencia del objeto sin tener que pasar por todas partes su índice. Por lo tanto, sugiero esta solución. Utiliza el operador de identidad !== , que utiliza para probar si dos referencias de objeto se refieren a la misma instancia de objeto.

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

Por supuesto, esto no solo funciona para el Strings.


23
Debería serlist = list.filter({ $0 != element })
Craig Grummitt

55
No si quieres consultar con el operador de identidad.
Daniel

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

2
Tenga en cuenta que si otros objetos hacen referencia a listesta eliminación, no se actualizarán las otras referencias de matriz ya que está asignando una nueva matriz a list. Solo una implicación sutil si elimina de las matrices con este enfoque.
Crashalot

1
El paradigma de programación funcional se basa en objetos inmutables. Es decir, no los cambias. En cambio, crea un nuevo objeto. Esto es lo que hace eliminar, asignar, reducir, etc. La lista será un objeto recién creado. En el fragmento de código anterior, estoy asignando de nuevo para enumerar un objeto recién creado. Eso funciona para mí, porque diseño mi código de una manera que sigue la programación funcional.
Daniel

44

Swift 5: Aquí hay una extensión fácil y genial para eliminar elementos en una matriz, sin 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"]

También funciona con otros tipos, como Intya que Elementes un tipo genérico:

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

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

1
Interesante esta matriz donde Elemento: Parte equitativa
Nicolas Manzini

1
Brillante. Aunque no funciona si comienza con una lista de Protocolos, ya que - El tipo de protocolo no puede cumplir con 'Equivalente' porque solo los tipos concretos pueden cumplir con los protocolos :-(
AW101

22

Para Swift4:

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

15

A partir de Xcode 10+, y de acuerdo con la sesión 223 de WWDC 2018, "Abrazando Algoritmos", un buen método en el futuro serámutating func removeAll(where predicate: (Element) throws -> Bool) rethrows

El ejemplo de 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."

ver la documentación de Apple

Entonces, en el ejemplo del OP, eliminando animales [2], "chimpancés":

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

Este método puede preferirse porque se escala bien (lineal frente a cuadrático), es legible y limpio. Tenga en cuenta que solo funciona en Xcode 10+, y al momento de escribir esto está en Beta.


removeAll (donde :) solo podrá en
Swift

14

Poca operación se relaciona con la matriz en Swift

Crear matriz

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

Agregar objeto en matriz

stringArray = stringArray + ["Five"]

Obtener valor del objeto de índice

let x = stringArray[1]

Añadir objeto

stringArray.append("At last position")

Insertar objeto en el índice

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

Eliminar objeto

stringArray.removeAtIndex(3)

Concat Object value

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

14

Podrías hacer eso. Primero asegúrese de que Dogrealmente exista en la matriz, luego quítelo. Agregue la fordeclaración si cree que Dogpuede suceder más de una vez en su matriz.

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

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

Si está seguro de que Dogsale de la matriz y sucedió solo una vez, simplemente haga eso:

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

Si tienes ambos, cadenas y 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)!)
        }
    }
}

¿Qué pasa si mi matriz no contiene cadenas?
Apqu

@apqu hizo otra actualización '|| objeto == Int () 'y' || object == String () 'son innecesarios
GuiSoySauce

el bucle de una matriz se vuelve contra la eficiencia. comprobar .filter, .compactMap
MLBDG


10

Eliminar elementos usando la matriz de índices:

  1. Matriz de cadenas 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 enteros 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]



Eliminar elementos utilizando el valor del elemento de otra matriz

  1. Matrices de enteros

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

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

44
Esta es una respuesta sencilla y es mucho más eficiente para una mejor codificación y una ejecución rápida.
El iOSDev

Hola @ Krunal: excelente respuesta, ¿podrías echar un vistazo a la siguiente pregunta (liberar imágenes de una matriz de imágenes): stackoverflow.com/questions/47735975/…
Programador del servidor

6

Con respecto a la alternativa de @ Suragch para "Eliminar elemento de índice desconocido":

Hay una versión más poderosa de "indexOf (element)" que coincidirá en un predicado en lugar del objeto en sí. Tiene el mismo nombre pero myObjects.indexOf {$ 0.property = valueToMatch} lo invoca. Devuelve el índice del primer elemento coincidente encontrado en la matriz myObjects.

Si el elemento es un objeto / estructura, es posible que desee eliminar ese elemento en función del valor de una de sus propiedades. Por ejemplo, tiene una clase Car que tiene la propiedad car.color y desea eliminar el automóvil "rojo" de su matriz de automóviles.

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

Previsiblemente, puede volver a trabajar esto para eliminar "todos" los autos rojos incorporando la declaración if anterior dentro de un ciclo de repetición / while y adjuntando un bloque else para establecer una bandera para "romper" el ciclo.


6

Swift 5

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

4

Si tiene una matriz de objetos personalizados, puede buscar por propiedad específica como esta:

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

o si quieres buscar por nombre por ejemplo

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

3

Esto debería hacerlo (no probado):

animals[2..3] = []

Editar: y necesita que sea una var, no una let, de lo contrario es una constante inmutable.


55
Cuando se utiliza un (sub) rango de una matriz existente para crear otra matriz, el rango debe tener 3 puntos. Lo anterior debe escribirse como animales [2 ... 3]
zevij

3

Se me ocurrió la siguiente extensión que se encarga de eliminar elementos de un Array, asumiendo los elementos en el 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]

Hola @nburk: excelente respuesta, ¿podrías echar un vistazo a la siguiente pregunta (liberar imágenes de una matriz de imágenes): stackoverflow.com/questions/47735975/…
Server Programmer

1

extensión para eliminar el objeto String

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

el desenvolvimiento forzado puede causar un bloqueo, creo que debería evitarlo en este caso.
user3206558

¿Qué es una función "mutante"?
AwesomeElephant8232

solía decir que esta función cambiará el self (matriz).
Varun Naharia

1

Uso esta extensión, casi la misma que la de Varun, pero esta (a continuación) es para todo uso:

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

1

Para eliminar elementos de una matriz, use los remove(at:)botones removeLast()y removeAll().

yourArray = [1,2,3,4]

Eliminar el valor en la posición 2

yourArray.remove(at: 2)

Eliminar el último valor de la matriz

yourArray.removeLast()

Elimina a todos los miembros del conjunto.

yourArray.removeAll()
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.