web-dev-qa-db-fra.com

Set (Collection) - Insérer plusieurs éléments

Set est une collection non ordonnée d'éléments uniques. Presque similaire au tableau.

Je veux ajouter/insérer plusieurs éléments dans un Set de String. Mais il n'y a qu'une seule méthode fournie qui ne peut insérer qu'un seul élément (accepte un seul élément Set comme argument de paramètre) et j'ai une collection de chaîne (id).

insérer (_:)

@discardableResult mutating func insert(_ newMember: Set.Element) -> (inserted: Bool, memberAfterInsert: Set.Element)

Comment puis je faire ça?

Ce que j'ai essayé:
J'ai essayé de créer une extension très similaire à la méthode insert(_:) mais elle peut accepter plusieurs éléments Set. Ce serait la même chose que l'utilisation de l'itération sur la collection, mais vous n'avez pas besoin de la gérer manuellement partout.

extension Set {

    @discardableResult mutating func insert(_ newMembers: [Set.Element]) -> (inserted: Bool, memberAfterInsert: Set.Element) {

        newMembers.forEach { (member) in
            self.insert(member)
        }
    }
}

Cela devrait fonctionner, si je retourne un tuple comme prévu, mais je ne sais pas comment et où (quelle ligne) et quoi renvoyer une valeur.

Voici un message d'erreur.

Retour manquant dans une fonction censée retourner '(inséré: Bool, memberAfterInsert: Set.Element)'

enter image description here

Quelle peut être la solution à cela. Existe-t-il une meilleure solution/approche pour gérer cette opération?

15
Krunal

Votre déclaration insert indique que la méthode retourne un Tuple: (inserted: Bool, memberAfterInsert: Set.Element), Mais votre méthode ne retourne rien.

Utilisez simplement:

@discardableResult mutating func insert(_ newMembers: [Set.Element]) {

    newMembers.forEach { (member) in
        self.insert(member)
    }
}

[~ # ~] mise à jour [~ # ~]

Le plus proche à obtenir est celui-ci je crois:

extension Set {

    @discardableResult mutating func insert(_ newMembers: [Set.Element]) -> [(inserted: Bool, memberAfterInsert: Set.Element)] {
        var returnArray: [(inserted: Bool, memberAfterInsert: Set.Element)] = []
        newMembers.forEach { (member) in
            returnArray.append(self.insert(member))
        }
        return returnArray
    }
}

Raisonnement:

Les docs à l'encart disent:

Valeur de retour

(true, newMember) Si newMember n'était pas contenu dans l'ensemble. Si un élément égal à newMember était déjà contenu dans l'ensemble, la méthode renvoie (false, oldMember), Où oldMember est l'élément qui était égal à newMember. Dans certains cas, oldMember peut être distingué de newMember par comparaison d'identité ou par d'autres moyens.

Par exemple, pour l'ensemble {1, 2, 3} Si vous essayez d'insérer 2, Le tuple renverra (false, 2), Car 2 Était déjà là. Le deuxième élément du tuple serait un objet de l'ensemble et non celui que vous avez fourni - ici avec Ints, il est impossible de le distinguer, car seul le nombre 2 Est égal à 2, Mais en fonction de Equatable mise en œuvre, vous pouvez avoir deux objets différents qui seraient évalués comme étant identiques. Dans ce cas, le deuxième argument pourrait être important pour nous.

Quoi qu'il en soit, ce que j'essaie de dire, c'est qu'un seul Tuple correspond donc à un singlenewMember que vous essayez d'insérer. Si vous essayez d'insérer plusieurs nouveaux membres, vous ne pouvez pas décrire cette insertion simplement en utilisant un seul tuple - certains de ces nouveaux membres peuvent déjà avoir été là, donc pour le premier argument serait false, certains autres membres pourrait être inséré avec succès, donc pour eux le premier argument de Tuple serait true.

Par conséquent, je crois que la bonne façon est de renvoyer un tableau de tuples [(inserted: Bool, memberAfterInsert: Set.Element)].

6
Milan Nosáľ

Cela a été souligné dans les commentaires sous la question, mais je voudrais indiquer clairement qu'il existe une méthode dans le même but:

mutating func formUnion<S>(_ other: S) where Element == S.Element, S : Sequence

Usage:

var attendees: Set = ["Alicia", "Bethany", "Diana"]
let visitors = ["Diana", "Marcia", "Nathaniel"]
attendees.formUnion(visitors)
print(attendees)
// Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]"

Source: développeur Apple


Il existe également une variante immuable qui renvoie une nouvelle instance contenant l'union:

func union<S>(_ other: S) -> Set<Set.Element> where Element == S.Element, S : Sequence

Usage:

let attendees: Set = ["Alicia", "Bethany", "Diana"]
let visitors = ["Marcia", "Nathaniel"]
let attendeesAndVisitors = attendees.union(visitors)
print(attendeesAndVisitors)
// Prints "["Diana", "Nathaniel", "Bethany", "Alicia", "Marcia"]"

Source: développeur Apple

23
Arkadii

Opérations des ensembles fondamentaux

enter image description here

union fonction immuable, retourne un nouvel ensemble avec les éléments de ceci et de l'ensemble donné.

func union(_ other: Self) -> Self 

formUnion (unionInPlace jusqu'à Swift version 3) fonction mutable, ajoute les éléments de l'ensemble donné à l'ensemble.

mutating func formUnion(_ other: Self)
1
yoAlex5