Home > OS >  Does performing contains on a set make lazy map redundant?
Does performing contains on a set make lazy map redundant?

Time:12-28

Suppose I have the following

let ids = mySet.lazy.map { $0.id }
ids.contains(...)

Does the .contains() function make lazy redundant? I'm assuming it has to perform map on the whole of mySet to be able to perform contains()? Or am I wrong?

CodePudding user response:

You are wrong.

Adding .lazy causes map to return a LazyMapSequence instead of an Array. When you call .contains on this LazyMapSequence, it will execute the mapping operation on each element as .contains checks it.

Imagine your set has 100 items. .contains quits as soon as it finds the item you are searching for, so if you get lucky and the first item in your Set satisfies .contains, then only that item will be .mapped and .contains will immediately return true.

Note that Sets are unordered, so the order it is searched is unspecified.

Try this in a Playground:

struct Person : Hashable {
    var id: Int
    var name: String
}

let mySet = Set([Person(id: 1, name: "Joe"),
                 Person(id: 2, name: "Abhijit"),
                 Person(id: 3, name: "Fred")])

let ids = mySet.lazy.map { (person) -> Int in print("mapped \(person)"); return person.id }
print(ids.contains(1))

Observe the output. When I tried it I got:

mapped Person(id: 1, name: "Joe")
true

Then remove .lazy and run it again. I got:

mapped Person(id: 1, name: "Joe")
mapped Person(id: 3, name: "Fred")
mapped Person(id: 2, name: "Abhijit")
true

So .lazy eliminates the need to run .map on every item. If .contains finds what it is looking for, then it is unnecessary to run .map on every item.

Note: If the Set does not contain the item you are searching for, then every item will be visited and .mapped before .contains can return false.


Now what if contains is called multiple times? Will that have to start from an “unmapped” sequence again? Or will it have stored the previously mapped values somewhere?

The second effect of lazy is that no storage is used to hold the intermediate mapped values. So calling contains multiple times will execute the mapping operation again for each set value that is accessed.

  • Related