【问题标题】:Class that iterate over a set迭代集合的类
【发布时间】:2017-03-10 21:09:13
【问题描述】:
class Ordered:
    def __init__(self,aset):
        self.aset = aset
    def __iter__(self):
        for v in sorted(self.aset): # iterate over list of values returned by sorted
            yield v

函数接受一个集合并返回一个列表

集合总是

s = {1, 2, 4, 8, 16}

例如:

s = {1, 2, 4, 8, 16}
i = iter(Ordered(s))
print(next(i))
print(next(i))
s.remove(8)
print(next(i))
s.add(32)
print(next(i))
print(next(i))

it should prints 1 2 4 16 32

但是当我的函数需要时

[next(i), next(i), s.remove(8), next(i), next(i), s.add(32), next(i)]

应该打印出来

[1, 2, None, 4, 16, None, 32]

但是,它会打印:

[1, 2, None, 4, 8, None, 16]

谁能告诉我如何解决它?谢谢

我在下面发布了我遇到的错误以帮助理解:

39 *Error: Failed [next(i), next(i), s.remove(8), next(i), next(i), s.add(32), next(i)] == [1, 2, None, 4, 16, None, 32]
      evaluated: [1, 2, None, 4, 8, None, 16] == [1, 2, None, 4, 16, None, 32]
42 *Error: [next(i), next(i), next(i), s.add(3), next(i), s.add(10), s.add(32), next(i), next(i), next(i)] raised exception; unevaluated: [1, 2, 4, None, 8, None, None, 10, 16, 32]
46 *Error: Failed [next(i), s.remove(2), s.remove(4), s.remove(8), next(i)] == [1, None, None, None, 16]
      evaluated: [1, None, None, None, 2] == [1, None, None, None, 16]
49 *Error: Failed [next(i), s.remove(2), next(i), s.remove(4), s.remove(8), next(i)] == [1, None, 4, None, None, 16]
      evaluated: [1, None, 2, None, None, 4] == [1, None, 4, None, None, 16]

【问题讨论】:

  • 删除某些内容后,迭代器不再有效。
  • 但是我该如何解决呢?
  • 谁能帮我解决这个问题?

标签: python iterable


【解决方案1】:

当您使用sorted 时,您会从集合中创建一个排序列表。该列表与创建它的原始集没有任何联系,并且不会反映对该集的任何更改。您必须自己跟踪更改,同时按排序顺序迭代元素。

跟踪删除的元素很简单:只需检查当前元素是否仍在原始集合中。跟踪新元素有点复杂。您可以使用heapq 模块并从集合中创建heap,而不是排序列表,然后您可以在迭代时向该堆添加新元素。要查找新元素,请创建原始集合的副本并在每次迭代中比较两者。另外,根据您的测试用例,您必须检查当前元素是否小于前一个元素,在这种情况下跳过它。

import heapq

class Ordered:

    def __init__(self,aset):
        self.aset = aset

    def __iter__(self):
        # memorize original elements
        known = set(self.aset)
        last = None

        # create heap
        heap = list(self.aset)
        heapq.heapify(heap)

        # yield from heap
        while heap:
            v = heapq.heappop(heap)
            if (v in self.aset and  # not removed
                    (last is None or last < v)): # not smaller than last
                yield v
            last = v

            # in case of new elements, update the heap
            diff = self.aset - known
            if diff:
                for x in self.aset - known:
                    heapq.heappush(heap, x)
                known = set(self.aset)

这适用于您的所有测试用例(未显示 si 的重新初始化):

>>> s = {1, 2, 4, 8, 16}
>>> i = iter(Ordered(s))
>>> [next(i), next(i), s.remove(8), next(i), next(i), s.add(32), next(i)]
[1, 2, None, 4, 16, None, 32]
>>> [next(i), next(i), next(i), s.add(3), next(i), s.add(10), s.add(32), next(i), next(i), next(i)]
[1, 2, 4, None, 8, None, None, 10, 16, 32])
>>> [next(i), s.remove(2), s.remove(4), s.remove(8), next(i)]
[1, None, None, None, 16]
>>> [next(i), s.remove(2), next(i), s.remove(4), s.remove(8), next(i)]
[1, None, 4, None, None, 16]

【讨论】:

    【解决方案2】:

    sorted() 函数对参数进行排序并返回一个列表。修改输入集不会影响排序列表。

    如果您希望迭代器反映对原始集合的更改,则迭代器将需要在每次迭代时检查集合的状态并做出适当的响应。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 2015-08-17
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 2021-10-22
      相关资源
      最近更新 更多