Adding new Elements to a Set in Swift

Updated: May 9, 2023 By: Wolf Post a comment

In Swift, you can add a new element to an existing set by using either the insert() method or the update() method.

Using the insert() method

The insert() method returns a tuple containing a Boolean value (that indicates whether the element was inserted) and the inserted element. If the element was not already present in your set, the method returns (true, newMember). If an element equal to newMember was already present in the set, the method returns (false, oldMember), where oldMember is the element that was equal to newMember. In some cases, oldMember may be distinguishable from newMember by identity comparison or some other means.

The words above might be boring and confusing. Here’s an example:

var colors = Set(["red", "green", "blue"])

// using insert() method
let result = colors.insert("yellow")
print(result) // (inserted: true, memberAfterInsert: "yellow")
print(colors) // ["red", "green", "blue", "yellow"]

let result2 = colors.insert("green")
print(result2) // (inserted: false, memberAfterInsert: "green")
print(colors) // ["red", "green", "blue", "yellow"]

Using the update() method

The update() method does the following:

  • Inserting a new element into your set if it is not already present, and returns nil.
  • Replacing an existing element if it has an equal value with the element you want to add and returns that replaced element.

Example:

var words: Set<String> = ["Sling", "Academy", "Swift", "iOS"]

// add a new element
var result1 = words.update(with: "Demon")
print(result1 as Any) // nil
print(words) // ["Sling", "iOS", "Swift", "Academy", "Demon"]

// add a value that already exists
words.update(with: "Sling")
var result2 = words.update(with: "Sling")
print(result2 as Any) // Optional("Sling")
print(words) // ["Sling", "iOS", "Swift", "Academy", "Demon"]

You may think “replacing an existing element if it has an equal value with the element you want to add” make no sense. I’m sorry if that was confusing. Let me explain in more detail in the next section of this article.

Advanced: More about the update() method

A set is a collection of unique elements, so it cannot have duplicate values. However, two elements can be equal in value but different in some other way, such as identity or reference. For example, if you have a set of custom objects that conform to the Hashable protocol, you can define how they are compared for equality and hashed. If you insert or update an element that has the same hash value and is equal to an existing element in the set, the existing element will be replaced by the new one. This may or may not change the actual contents of the set, depending on how you define equality for your custom objects.

A code example is worth more than a thousand words:

// A custom class that conforms to Hashable
class Person: Hashable {
    var name: String
    var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    // Define how two persons are compared for equality
    static func == (lhs: Person, rhs: Person) -> Bool {
        return lhs.name == rhs.name && lhs.age == rhs.age
    }

    // Define how a person is hashed
    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
        hasher.combine(age)
    }
}

// Create a set of persons
var persons: Set<Person> = [
    Person(name: "Wolf", age: 99),
    Person(name: "Voldermort", age: 68),
    Person(name: "Dracula", age: 1100),
]


// Create a new person with the same name and age as "Wolf"
// I think "Wolf" is a nice name for a man
// There is also a character named "Wolf" in the game "Sekiro: Shadows Die Twice"
let newWolf = Person(name: "Wolf", age: 99)

// Update the set with the new person
let oldWolf = persons.update(with: newWolf)

// Print the old and new persons
print("Old person: \(oldWolf!.name), \(oldWolf!.age)")
print("New person: \(newWolf.name), \(newWolf.age)")

// Check if they are equal in value
print("Are they equal? \(oldWolf == newWolf)") // true

// Check if they are identical (same reference)
print("Are they identical? \(oldWolf === newWolf)") // false

// Print the persons in the set after updating
for person in persons {
    print("\(person.name), \(person.age)")
}

/*
Voldermort, 68
Wolf, 99
Dracula, 1100
*/

That’s it. Happy coding & have a nice day!