实现一个自定义迭代器,该迭代器会跳过WeakSet中的nil个元素

MH175

我正在实现一个WeakSet,将其元素弱地包装为a WeakWrapper,以便不增加其保留数。

我的问题是,如何创建一个迭代器,以便可以跳过已被释放的元素(即are nil来遍历这些元素

请注意,我正在尝试优化迭代;插入/删除相对较慢是可以的,但是设置迭代器的性能成本应该很小/没有。

这是我WeakSet的基本形式。我可以致电clean()移除WeakWrapper其对象已被释放的:

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
    }
}

我希望能够做这样的事情,其中​​生成的元素是type的基础非null元素T,而不是包装的元素:

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

var weakSet = WeakSet<MyObject>()
for myObject in weakSet {
    myObject.doSomething()
}
马丁·R

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

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

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

它也可以在不使用的情况下工作lazy,但是一旦makeIterator()被调用,就会急切地创建一个包含所有非nil对象的数组

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

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())
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在自定义反向矢量迭代器中,看不到第一个元素

为什么boost :: python迭代器会跳过第一个元素?

在C ++中,可以实现一个迭代器接口,在该接口中,前进会使“当前”元素无效?

如何创建一个迭代器,该迭代器生成由Rust中的索引列表指定的集合元素?

在std :: map中,获得一个迭代器,该迭代器指向比键更大的LAST元素

实现一个QAbstractItemModel迭代器

了解实现自定义迭代器

如何跳过Rust迭代器中的第N个元素?

Java删除迭代器,该迭代器删除同一列表中的另一个元素

如何在Rust中定义一个包含可迭代项的结构上的迭代器?

为什么`zip`从第一个迭代器中又吃了一个元素?

自定义迭代器

排除最后一个元素的迭代器

向量的最后一个元素的迭代器

如何获得从最后一个元素开始的迭代器

列出元素的下一个迭代器

接受迭代器并返回迭代器中第一个可被 2 整除的元素的函数

我正在尝试为 Angular 中的 formGroup 制作一个自定义验证器。但是我无法在 formGroup 中实现自定义验证器

如何使迭代器指向与C ++集合中的另一个元素相同的元素?

使用迭代器中除最后一个元素之外的所有元素

创建自定义迭代器时,如何获得std :: pair的第一个和第二个?

C#自定义迭代器实现

为自定义 std::map 迭代器实现 erase()

如何为Map实现创建自定义迭代器?

为动态矩阵类实现自定义迭代器

迭代器擦除 C++ 的自定义实现

在同一个类中实现多个迭代器

迭代器中的第n个元素

创建一个蛮力迭代器