首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实现自定义迭代器,该迭代器跳过WeakSet中的零元素

实现自定义迭代器,该迭代器跳过WeakSet中的零元素
EN

Stack Overflow用户
提问于 2017-09-24 05:04:01
回答 1查看 220关注 0票数 4

我正在实现一个WeakSet,它将其元素弱包装在一个WeakWrapper中,以避免增加它们的保留计数。

我的问题是,我如何创建一个迭代器,这样我就可以迭代那些已经被释放的元素(也就是nil)。

请注意,我正试图在迭代过程中进行优化;如果插入/删除相对较慢,也可以,但是设置迭代器应该不需要多少/没有性能成本。

这是我的WeakSet的基本形式。我可以调用clean()来删除其对象已被解除分配的WeakWrapper

代码语言:javascript
复制
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
    }
}

我希望能够这样做,其中生成的元素是T类型的基础非零元素,而不是包装元素:

代码语言:javascript
复制
class MyObject: NSObject {
    func doSomething() { }
}

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

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-24 05:27:01

一种可能的解决方案,使用Swift标准库的内置方法:

代码语言:javascript
复制
extension WeakSet: Sequence {
    func makeIterator() -> AnyIterator<T> {
        return AnyIterator(self.set.lazy.flatMap { $0.obj }.makeIterator())
    }
}

从set的惰性视图开始,使用flatMap创建其非零对象的(惰性)集合。

它在没有lazy的情况下也能工作,但是一旦调用makeIterator(),就会急切地创建一个包含所有非零对象的数组。

另一种解决方案,使用自定义迭代器类型:

代码语言:javascript
复制
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())
    }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46386758

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档