Set (Collection) - Insert multiple elements
Swift Set Union
[Swift Set operations]
a.union(b) - a ∪ b
- the result set contains all elements from a
and b
union
- immutable functionunionInPlace
(up to Swift 3) =>formUnion
- mutable function
[Mutable vs Immutable]
Read more here
It was pointed out in the comments under the question, but I'd like to clearly state that there is a method for that very same purpose:
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: Apple Developer
There is also an immutable variant which returns a new instance containing the 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: Apple Developer
Your insert
declaration states that the method is returning a tuple: (inserted: Bool, memberAfterInsert: Set.Element)
, but your method does not return anything.
Just use:
@discardableResult mutating func insert(_ newMembers: [Set.Element]) {
newMembers.forEach { (member) in
self.insert(member)
}
}
UPDATE
The closest to get is this I believe:
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
}
}
Reasoning:
The docs to the insert say:
Return Value
(true, newMember)
ifnewMember
was not contained in the set. If an element equal tonewMember
was already contained in the set, the method returns(false, oldMember)
, whereoldMember
is the element that was equal tonewMember
. In some cases,oldMember
may be distinguishable fromnewMember
by identity comparison or some other means.
E.g., for set {1, 2, 3}
if you try to insert 2
, the tuple will return (false, 2)
, because 2
was already there. The second item of the tuple would be object from the set and not the one you provided - here with Ints it's indistinguishable, since only number 2
is equal to 2
, but depending on Equatable
implementation you can have two different objects that would be evaluated as the same. In that case the second argument might be important for us.
Anyway, what I am trying to say is, that a single tuple therefore corresponds to a single newMember
that you try to insert. If you try to insert multiple new members, you cannot describe that insertion just by using a single tuple - some of those new members might have already been there, thus for the the first argument would be false
, some other members might be successfully inserted, thus for them the first argument of tuple would be true
.
Therefore I believe the correct way is to return an array of tuples [(inserted: Bool, memberAfterInsert: Set.Element)]
.