Question about Set intersection function

Swift: 5.5.1
Why always return intersection items of set1?
Is there any way to return intersection items of set2?
thx

Result:
===== set1 =====
[Item: 0x00006000026a44c0] name: 1, price: 1, type: set1
[Item: 0x00006000026a4f80] name: 2, price: 2, type: set1

===== set2 =====
[Item: 0x00006000026a7840] name: 1, price: 1, type: set2
[Item: 0x00006000026a7880] name: 2, price: 2, type: set2
[Item: 0x00006000026a78c0] name: 3, price: 3, type: set2

===== set1 intersection set2 =====
[Item: 0x00006000026a44c0] name: 1, price: 1, type: set1
[Item: 0x00006000026a4f80] name: 2, price: 2, type: set1

===== set2 intersection set1 =====
[Item: 0x00006000026a44c0] name: 1, price: 1, type: set1
[Item: 0x00006000026a4f80] name: 2, price: 2, type: set1
class Item: Hashable, CustomStringConvertible {
    var name: String
    var price: String
    var type: String
    var description: String {
        let address = Unmanaged.passUnretained(self).toOpaque()
        return "[Item: \(address)] name: \(self.name), price: \(self.price), type: \(self.type)"
    }
    
    init(name: String, price: String, type: String) {
        self.name = name
        self.price = price
        self.type = type
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(self.name)
        hasher.combine(self.price)
    }
    
    static func == (left: Item, right: Item) -> Bool {
        left.name == right.name && left.price == right.price
    }
}

let set1: Set<Item> = [Item(name: "1", price: "1", type: "set1"),
                       Item(name: "2", price: "2", type: "set1")]
print("\n===== set1 =====")
set1.forEach { print($0) }

let set2: Set<Item> = [Item(name: "1", price: "1", type: "set2"),
                       Item(name: "2", price: "2", type: "set2"),
                       Item(name: "3", price: "3", type: "set2")]
print("\n===== set2 =====")
set2.forEach { print($0) }

let intersection1 = set1.intersection(set2)
print("\n===== set1 intersection =====")
intersection1.forEach { print($0) }

let intersection2 = set2.intersection(set1)
print("\n===== set2 intersection =====")
intersection2.forEach { print($0) }

because set1 is smaller. it's a regression being discussed here.

If you care about which one is returned, then your implementation of the Hashable is weird. That’s an indication that instead of Set you should be using Dictionary, with name and price used as a key and description or even entire item as a value.

Instead of making Item conform to Hashable, consider making a new type ItemKey storing only name and price, with compiler-synthesized conformance.

1 Like