Implement a custom iterator that skips zero elements in WeakSet

I implement WeakSetthat weakly transfers its elements in WeakWrapper, so as not to increase their number of deductions.

My question is: how to create an iterator so that I can iterate over elements that are missing those that were freed (i.e. nil).

Note that I'm trying to optimize the iteration; this is normal if insertion / deletion is relatively slower, but there should be little / no performance for installing an iterator.

Here is mine WeakSetin its basic form. I can call clean()to delete WeakWrapperwhose objects have been freed:

struct WeakSet<T> where T: AnyObject & Hashable {
    private var set: Set<WeakWrapper<T>> = []

    mutating func insert(_ elem: T) {
        self.set.insert(WeakWrapper<T>(elem))
    }

    mutating func remove(_ elem: T) {
        self.set.remove(WeakWrapper<T>(elem))
    }

    mutating func clean() {
       for elem in set {
           if elem.obj == nil {
               self.set.remove(elem)
           }
       }
   }
}

fileprivate class WeakWrapper<T>: Hashable where T: AnyObject {
    weak var obj: T?
    let hashValue: Int

    init(_ obj: T) {
        self.obj = obj
        self.hashValue = ObjectIdentifier(obj).hashValue
     }

    static func ==(lhs: WeakWrapper, rhs: WeakWrapper) -> Bool {
        return lhs.hashValue == rhs.hashValue
    }
}

- , -nil T, :

class MyObject: NSObject {
    func doSomething() { }
}

var weakSet = WeakSet<MyObject>()
for myObject in weakSet {
    myObject.doSomething()
}
+4
1

, Swift :

extension WeakSet: Sequence {
    func makeIterator() -> AnyIterator<T> {
        return AnyIterator(self.set.lazy.flatMap { $0.obj }.makeIterator())
    }
}

, () non-nil flatMap.

lazy, -nil , makeIterator().

:

struct WeakSetIterator<T>: IteratorProtocol where T: AnyObject {
    fileprivate var iter: SetIterator<WeakWrapper<T>>

    mutating func next() -> T? {
        while let wrapper = iter.next() {
            if let obj = wrapper.obj { return obj }
        }
        return nil
    }
}

extension WeakSet: Sequence {
    func makeIterator() -> WeakSetIterator<T> {
        return WeakSetIterator(iter: self.set.makeIterator())
    }
}
+2

Source: https://habr.com/ru/post/1686278/


All Articles