Comment supprimer un élément d'un tableau dans Swift

236

Comment puis-je supprimer / supprimer un élément d'un tableau dans le nouveau langage d'Apple Swift?

Voici du code:

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

Comment l'élément pourrait-il animals[2]être supprimé du tableau?

Léopold Joy
la source

Réponses:

300

Le letmot-clé sert à déclarer des constantes qui ne peuvent pas être modifiées. Si vous souhaitez modifier une variable, vous devez utiliser à la varplace, par exemple:

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

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

Une alternative non mutante qui gardera la collection d'origine inchangée consiste à utiliser filterpour créer une nouvelle collection sans les éléments que vous souhaitez supprimer, par exemple:

let pets = animals.filter { $0 != "chimps" }
mythz
la source
7
FYI: removerenvoie l'élément supprimé:let animal = animals.remove(at: 2)
2Toad
1
pouvons-nous filtrer uniquement en fonction de l'index ??
shaqir a dit
@shaqirsaiyed Vous pouvez filtrer sur n'importe quel prédicat que vous pouvez imaginer. par exemple, vous pouvez filtrer tous les animaux qui se terminent par un «s».
Womble
ajouter des animaux = des animaux de compagnie
Puji Wahono
197

Donné

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

Supprimer le premier élément

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

Supprimer le dernier élément

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

Supprimer l'élément à l'index

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

Supprimer l'élément d'index inconnu

Pour un seul élément

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

Pour plusieurs éléments

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

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

Remarques

  • Les méthodes ci-dessus modifient le tableau en place (sauf pour filter) et retournent l'élément qui a été supprimé.
  • Guide rapide pour réduire le filtre de carte
  • Si vous ne souhaitez pas modifier le tableau d'origine, vous pouvez utiliser dropFirstou dropLastpour créer un nouveau tableau.

Mise à jour vers Swift 5.2

Suragch
la source
Merci pour ces exemples, si vous supprimez un élément d'index inconnu > pour plusieurs éléments , quelle fermeture écririez-vous pour supprimer chimps && moosepar exemple? Je recherche quelque chose de différent de{$0 != "chimps" && $0 != "moose"}
161

Les réponses ci-dessus semblent supposer que vous connaissez l'index de l'élément que vous souhaitez supprimer.

Souvent, vous connaissez la référence à l'objet que vous souhaitez supprimer dans le tableau. (Vous avez parcouru votre tableau et l'avez trouvé, par exemple) Dans de tels cas, il pourrait être plus facile de travailler directement avec la référence d'objet sans avoir à passer partout son index. Par conséquent, je suggère cette solution. Il utilise l' opérateur d'identité !== , que vous utilisez pour tester si deux références d'objet font référence à la même instance d'objet.

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

Bien sûr, cela ne fonctionne pas seulement pour l' Stringart.

Daniel
la source
23
Devrait êtrelist = list.filter({ $0 != element })
Craig Grummitt
5
Pas si vous souhaitez vérifier auprès de l'opérateur d'identité.
Daniel
3
array.indexOf({ $0 == obj })
jrc
2
Notez que si d'autres objets référencent listcette suppression ne mettra pas à jour les autres références de tableau puisque vous affectez un nouveau tableau à list. Juste une implication subtile si vous supprimez des tableaux avec cette approche.
Crashalot
1
Le paradigme de programmation fonctionnelle repose sur des objets immuables. C'est-à-dire que vous ne les changez pas. Au lieu de cela, vous créez un nouvel objet. C'est ce que fait supprimer, mapper, réduire, etc. La liste sera un objet nouvellement créé. Dans l'extrait de code ci-dessus, je réattribue à la liste un objet nouvellement créé. Cela fonctionne pour moi, car je conçois mon code d'une manière qui suit la programmation fonctionnelle.
Daniel
44

Swift 5: Voici une extension cool et facile à supprimer des éléments dans un tableau, sans filtrage:

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

}

Utilisation:

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

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

Fonctionne également avec d'autres types, car Intpuisque Elementest un type générique:

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

myArray.remove(object: objectToRemove) // [4, 8, 6, 2]
Skaal
la source
1
Intéressant ce tableau où élément: partie équitable
Nicolas Manzini
1
Brillant. Bien que cela ne fonctionne pas si vous commencez avec une liste de protocoles, car - Le type de protocole ne peut pas se conformer à 'Equatable' car seuls les types concrets peuvent se conformer aux protocoles :-(
AW101
22

Pour Swift4:

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

la source
15

À partir de Xcode 10+, et selon la session 223 de la WWDC 2018, "Embracing Algorithms", une bonne méthode pour l'avenir seramutating func removeAll(where predicate: (Element) throws -> Bool) rethrows

Exemple d'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."

voir la documentation d'Apple

Ainsi, dans l'exemple du PO, retirer les animaux [2], "chimpanzés":

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

Cette méthode peut être préférée car elle évolue bien (linéaire vs quadratique), est lisible et propre. Gardez à l'esprit que cela ne fonctionne que dans Xcode 10+, et au moment de l'écriture, c'est en version bêta.

davidrynn
la source
removeAll (où :) ne pourra que dans swift 4.2
Vlad Pulichev
14

Peu d'opérations concernent Array in Swift

Créer un tableau

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

Ajouter un objet dans un tableau

stringArray = stringArray + ["Five"]

Obtenir la valeur de l'objet Index

let x = stringArray[1]

Ajouter un objet

stringArray.append("At last position")

Insérer un objet à l'index

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

Supprimer un objet

stringArray.removeAtIndex(3)

Valeur de l'objet Concat

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

Tu pourrais faire ça. Assurez-vous d'abord Dogqu'il existe réellement dans le tableau, puis supprimez-le. Ajoutez l' forinstruction si vous pensez que cela Dogpeut se produire plusieurs fois sur votre baie.

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

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

Si vous êtes sûr de Dogquitter le tableau et que vous ne l'avez fait qu'une seule fois, faites-le:

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

Si vous avez les deux, des chaînes et des nombres

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
la source
Que faire si mon tableau ne contient pas de chaînes?
Apqu
@apqu a fait une autre mise à jour '|| objet == Int () 'et' || object == String () 'sont inutiles
GuiSoySauce
boucler un tableau augmente l'efficacité. check .filter, .compactMap
MLBDG
10

Supprimer des éléments à l'aide du tableau d'index:

  1. Tableau de chaînes et d'index

    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. Tableau d'entiers et d'index

    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]



Supprimer des éléments à l'aide de la valeur d'élément d'un autre tableau

  1. Tableaux d'entiers

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

    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
la source
4
Il s'agit d'une seule réponse et elle est beaucoup plus efficace pour un meilleur codage et une exécution rapide.
Le iOSDev du
Salut @ Krunal - excellente réponse, pourriez-vous jeter un oeil à la question suivante (libérer des images à partir d'un tableau d'images): stackoverflow.com/questions/47735975/…
Server Programmer
6

Concernant l'alternative de @ Suragch à "Supprimer l'élément d'index inconnu":

Il existe une version plus puissante de "indexOf (element)" qui correspondra à un prédicat au lieu de l'objet lui-même. Il porte le même nom mais il est appelé par myObjects.indexOf {$ 0.property = valueToMatch}. Il renvoie l'index du premier élément correspondant trouvé dans le tableau myObjects.

Si l'élément est un objet / une structure, vous souhaiterez peut-être supprimer cet élément en fonction de la valeur de l'une de ses propriétés. Par exemple, vous avez une classe Car ayant la propriété car.color et vous souhaitez supprimer la voiture "rouge" de votre tableau de voitures.

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

De manière prévisible, vous pouvez retravailler cela pour supprimer "toutes" les voitures rouges en incorporant l'instruction if ci-dessus dans une boucle repeat / while, et en attachant un bloc else pour définir un drapeau pour "sortir" de la boucle.

ObjectiveTC
la source
6

Swift 5

guard let index = orders.firstIndex(of: videoID) else { return }
orders.remove(at: index)
Jérôme
la source
4

Si vous avez un tableau d'objets personnalisés, vous pouvez rechercher par propriété spécifique comme celle-ci:

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

ou si vous voulez rechercher par nom par exemple

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

Cela devrait le faire (non testé):

animals[2..3] = []

Edit: et vous devez en faire un var, pas un let, sinon c'est une constante immuable.

Fichier analogique
la source
5
Lorsque vous utilisez une (sous) plage d'un tableau existant pour créer un autre tableau, la plage doit avoir 3 points. Ce qui précède devrait être écrit comme des animaux [2 ... 3]
zevij
3

J'ai proposé l'extension suivante qui prend en charge la suppression d'éléments d'un Array, en supposant que les éléments dans l' Arrayimplémentation 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)
  }

}

Usage:

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

var test2 = [1, 2, 1, 2]
test2.removeFirstEqualItem(2) // [1, 1, 2]
nburk
la source
Salut @nburk - excellente réponse, pourriez-vous jeter un oeil à la question suivante (libérer des images à partir d'un tableau d'images): stackoverflow.com/questions/47735975/…
Server Programmer
1

extension pour supprimer l'objet String

extension Array {
    mutating func delete(element: String) {
        self = self.filter() { $0 as! String != element }
    }
}
Varun Naharia
la source
le déballage forcé peut provoquer un crash, je pense que vous devriez l'éviter dans ce cas.
user3206558
Qu'est-ce qu'une fonction "mutante"?
AwesomeElephant8232
il avait l'habitude de dire que cette fonction changera le self (array).
Varun Naharia
1

J'utilise cette extension, presque la même que celle de Varun, mais celle-ci (ci-dessous) est polyvalente:

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

Pour supprimer des éléments d'un tableau, utilisez les touches remove(at:), removeLast()et removeAll().

yourArray = [1,2,3,4]

Supprimer la valeur à 2 positions

yourArray.remove(at: 2)

Supprimer la dernière valeur du tableau

yourArray.removeLast()

Supprime tous les membres de l'ensemble

yourArray.removeAll()
PatelFab
la source