Menu
Coddy logo textTech

Equatable

Part of the Object Oriented Programming section of Coddy's Swift journey. Lesson 38 of 57.

Equatable gives a type the == and != operators. For structs and enums whose properties are all Equatable, declaring the conformance is enough, and Swift compares every property:

struct Card: Equatable {
    let rank: Int
    let suit: String
}

let a = Card(rank: 10, suit: "hearts")
let b = Card(rank: 10, suit: "hearts")
print(a == b)
print(a != Card(rank: 2, suit: "hearts"))

Output:

true
true

To compare only some properties, write static func == yourself. Here two users are equal when their ids match, whatever their names:

struct User: Equatable {
    let id: Int
    var name: String

    static func == (lhs: User, rhs: User) -> Bool {
        lhs.id == rhs.id
    }
}

print(User(id: 1, name: "Ada") == User(id: 1, name: "Ada L."))
print(User(id: 1, name: "Ada") == User(id: 2, name: "Ada"))

Output:

true
false

Equatable unlocks standard methods that need comparison, such as contains(_:), firstIndex(of:) and == on whole arrays:

struct Point: Equatable {
    let x: Int, y: Int
}

let path = [Point(x: 0, y: 0), Point(x: 1, y: 2)]
print(path.contains(Point(x: 1, y: 2)))
print(path.firstIndex(of: Point(x: 1, y: 2))!)
print(path == [Point(x: 0, y: 0), Point(x: 1, y: 2)])

Output:

true
1
true

Classes do not get == for free: they compare identity with ===. A class that should compare by value must implement == itself:

class Color: Equatable {
    let hex: String
    init(hex: String) { self.hex = hex }
    static func == (lhs: Color, rhs: Color) -> Bool { lhs.hex == rhs.hex }
}
challenge icon

Challenge

Easy

Product has sku, name and price. Two products are the same when their sku matches, whatever the other fields say. Make Product conform to Equatable with a custom ==, then complete mergeCatalog(_:), which keeps the first occurrence of every product (using contains) and returns sku name price lines followed by removed: 2.

The supplied code reads products as sku,name,price lines and prints each returned line.

Your code goes in Product.swift and Functions.swift. main.swift holds the supplied input/output code and cannot be edited.

Try it yourself

// Supplied input/output code: keep it as it is
var input: [String] = []
while let line = readLine() { input.append(line) }
let products = input.map { line -> Product in
    let p = line.split(separator: ",").map(String.init)
    return Product(sku: p[0], name: p[1], price: Int(p[2])!)
}
for line in mergeCatalog(products) { print(line) }
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming

Practice on your own: Swift playground