将一对发电机转变为一对发电机

时间:2017-11-06 22:28:38

标签: python tuples generator

我如何转换成对的生成器(元组):

tuple_gen = (i for i in [(1, "a"), (2, "b"), (3, "c")])

分成两个生成[1, 2, 3]["a", "b", "c"]

的生成器

我需要单独处理元组的第一个和第二个元素,处理函数需要迭代。

生成器非常大(数百万项),所以除非没有其他解决方案,否则我希望避免同时将所有项目都存储在内存中。

4 个答案:

答案 0 :(得分:1)

您可以使用itertools包中的tee函数创建n个不同的迭代器。然后,您将分别迭代它们:

from itertools impor tee

i1, i2 = tee(tuple_gen, n=2)
firsts = (x[0] for x in i1)
seconds = (x[1] for x in i2)

答案 1 :(得分:1)

这里存在根本问题。假设您获得了两个迭代器iter1iter2,并将iter1传递给了一个吃掉整个事物的函数:

def consume(iterable):
    for thing in iterable:
        do_stuff_with(thing)

consume(iter1)

那将需要遍历所有tuple_gen来获取第一项,然后你对第二项做什么?除非您重新运行生成器以再次获取第二个项目,否则您需要将所有这些项目存储在内存中,除非您可以将它们保存到磁盘或其他内容中,因此您不会比将它们保存到更好的状态。您只需将tuple_gen转储到列表中。

如果这样做,你必须并行使用迭代器,或者运行底层生成器两次,或者花费大量内存来保存你不处理的元组元素,以便其他迭代器可以覆盖它们。遗憾的是,并行使用迭代器将需要重写消费者函数或在单​​独的线程中运行它们。如果可以的话,运行两次发生器是最简单的,但并不总是一个选项。

答案 2 :(得分:0)

您可以使用itertools进行操作,如下所示:

>>>from itertools import chain, izip, imap
>>>tuple_gen = (i for i in [(1, "a"), (2, "b"), (3, "c")])
>>>nums_gen, letters_gen = imap(lambda x: chain(x), izip(*tuple_gen))
>>>list(nums_gen)
[1, 2, 3]
>>>list(letters_gen)
['a', 'b', 'c']

注意

对于 python3 izip只是zipimap只是map

答案 3 :(得分:-1)

案例1

我不知道它来自[(1, "a"), (2, "b"), (3, "c")] 但如果它来自下面的代码

gen1 = (i for i in  [1,2,3])
gen2 = (i for i in ["a", "b", "c"])
tuple_gen = (i for i in zip(gen1, gen2))

您可以直接使用gen1gen2

案例2

如果您已经创建了列表[(1, "a"), (2, "b"), (3, "c")],并且只是不想创建列表两次。你可以这样做。

lst = [(1, "a"), (2, "b"), (3, "c")]
gen1 = (i[0] for i in lst)
gen2 = (i[1] for i in lst)

案例3

否则,只需创建一个列表,但它会占用CPU资源来扩展生成器。这是你不想要的。

tuple_gen = (i for i in [(1, "a"), (2, "b"), (3, "c")])
tmp = list(tuple_gen)
gen1 = iter(tmp)
gen2 = iter(tmp)

我认为没有办法将生成器,迭代器重置到第一个位置。