【问题标题】:Using itertools.tee to duplicate a nested iterator (ie itertools.groupby)使用 itertools.tee 复制一个嵌套的迭代器(即 itertools.groupby)
【发布时间】:2019-05-28 09:43:07
【问题描述】:

我正在读取一个文件(同时执行一些昂贵的逻辑),我需要在不同的函数中迭代多次,所以我真的只想读取和解析一次文件。

解析函数解析文件并返回一个itertools.groupby对象。

def parse_file():
    ...
    return itertools.groupby(lines, key=keyfunc)

我想过做以下事情:

csv_file_content = read_csv_file()

file_content_1, file_content_2 = itertools.tee(csv_file_content, 2)

foo(file_content_1)
bar(file_content_2)

但是,itertools.tee 似乎只能“复制”外部迭代器,而内部(嵌套)迭代器仍然引用原始迭代器(因此在迭代 1st sup> itertools.tee 返回的迭代器)。

独立 MCVE:

from itertools import groupby, tee

li = [{'name': 'a', 'id': 1},
      {'name': 'a', 'id': 2},
      {'name': 'b', 'id': 3},
      {'name': 'b', 'id': 4},
      {'name': 'c', 'id': 5},
      {'name': 'c', 'id': 6}]

groupby_obj = groupby(li, key=lambda x:x['name'])
tee_obj1, tee_obj2 = tee(groupby_obj, 2)

print(id(tee_obj1))
for group, data in tee_obj1:
    print(group)
    print(id(data))
    for i in data:
        print(i)

print('----')

print(id(tee_obj2))
for group, data in tee_obj2:
    print(group)
    print(id(data))
    for i in data:
        print(i)

输出

2380054450440
a
2380053623136
{'name': 'a', 'id': 1}
{'name': 'a', 'id': 2}
b
2380030915976
{'name': 'b', 'id': 3}
{'name': 'b', 'id': 4}
c
2380054184344
{'name': 'c', 'id': 5}
{'name': 'c', 'id': 6}
----
2380064387336
a
2380053623136  # same ID as above
b
2380030915976  # same ID as above 
c
2380054184344  # same ID as above

我们如何有效地复制嵌套迭代器?

【问题讨论】:

  • 但是如果你使用内部迭代器,你不会读取文件两次吗?
  • 最好将所有内容硬编码到列表中。
  • 看来grouped_object即使在tee也不能使用两次。这种并行不起作用:tee_obj1, tee_obj2 = groupby_obj, groupby_obj。但我想这给出了预期的结果:tee_obj1, tee_obj2 = copy.deepcopy(groupby_obj), groupby_obj。我猜..
  • “如何递归复制迭代器”无法正确回答(或没有解决方案),如stackoverflow.com/questions/42132731/… 此处所述,但在您的情况下,deepcopy 似乎解决了它。

标签: python iterator itertools


【解决方案1】:

似乎grouped_object (class 'itertools.groupby') 被消费了一次,即使在itertools.tee 中也是如此。 同样grouped_object 的并行分配也不起作用:

tee_obj1, tee_obj2 = groupby_obj, groupby_obj

有效的是copy 的深层grouped_object

tee_obj1, tee_obj2 = copy.deepcopy(groupby_obj), groupby_obj

【讨论】:

  • "似乎 grouped_objectct (class 'itertools.groupby') 被使用一次,即使在 itertools.tee 中也是如此" 我不认为这是真的,否则 a b c 不会被输出第二次。尽管我希望使用比deepcopy 更优雅的东西,但我会接受这个答案。谢谢!
  • 正确的是,作为每个 groupby 迭代的“值”返回的 grouper 对象不能是 tee'd。
猜你喜欢
  • 1970-01-01
  • 2020-07-08
  • 2019-05-16
  • 1970-01-01
  • 2016-12-02
  • 2019-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多