如何将一个迭代器拆分为两个?

时间:2015-06-15 22:35:04

标签: python

如何在不迭代两次或使用额外内存存储所有数据的情况下将一个迭代器拆分为两个?

当您可以将所有内容存储在内存中时的解决方案:

class SomeIterable(object):
    def __iter__(self):
        for i in range(10):
            yield {'a': i, 'b': i * 2}


def a(some_iterator):
    for item in some_iterator:
        print(item)


def b(some_iterator):
    for item in some_iterator:
        print(item)


s = SomeIterable()

a((si['a'] for si in s))
b((si['b'] for si in s))

或者你可以迭代两次,

<?php
// Get the PHP helper library from twilio.com/docs/php/install
require_once('/path/to/twilio-php/Services/Twilio.php'); // Loads the library

// Your Account Sid and Auth Token from twilio.com/user/account
$accountSid = "ACYYYYYYYYYY"; 
$authToken = "XXXXXXXXX"; 
$client = new Services_Twilio($accountSid,$authToken);

// Get an object from its sid. If you do not have a sid,
// check out the list resource examples on this page
$member = $client->account->queues->get('QU5ef8732a3c49700934481addd5ce1659')->members->get("Front");
$member->update(array(
    "Url" => "https://dl.dropboxusercontent.com/u/11489766/learn/voice.xml",
    "Method" => "POST"
));
echo $member->wait_time;

但是,如果我只想迭代一次,我该怎么做呢?

3 个答案:

答案 0 :(得分:2)

如果使用两个迭代器的函数不在您的控制之下,并且在使用所有迭代器内容之前没有将程序控制权返回给您的代码,则无法执行您想要的操作。您需要在函数调用之间保存内存中的所有数据,或者为第二个函数重新生成迭代器。

现在,如果您的函数是生成器(在从输入中消耗了少量项目后返回到代码中),则可以使其与itertools.tee一起使用。如果您可以一次使用输入数据的各个部分调用一个或两个函数,然后以某种方式将重复调用的结果一起编译到所需的输出中,则可能还有一些其他部分解决方法。否则你可能会失去运气

答案 1 :(得分:2)

根据评论中的说明,ab是您无法重写的外部库函数,但可以交错执行。在这种情况下,你想要的是什么,但它几乎需要线程:

import multiprocessing.pool # for ThreadPool, not multiprocessing
import Queue

_endofinput = object()

def _queueiter(queue):
    while True:
        item = queue.get()
        if item is _endofinput:
            break
        yield item

def parallel_execute(funcs, iterable, maxqueue):
    '''Interleaves the execution of funcs[0](iterable), funcs[1](iterable), etc.

    No function is allowed to lag more than maxqueue items behind another.
    (This will require adjustment if a function might return before consuming
    all input.)

    Makes only one pass over iterable.

    '''

    queues = [Queue.Queue(maxsize=maxqueue) for func in funcs]
    queueiters = [_queueiter(queue) for queue in queues]
    threadpool = multiprocessing.pool.ThreadPool(processes=len(funcs))

    results = threadpool.map_async(lambda (f, x): f(x), zip(funcs, queueiters))

    for item in iterable:
        for queue in queues:
            queue.put(item)

    for queue in queues:
        queue.put(_endofinput)

    threadpool.close()
    return results.get()

答案 2 :(得分:1)

好的,如果你的函数是无状态的,但仍然期望一个可迭代的参数,并且这是整个问题,那么这应该做:

for si in s:
    a([si['a']])
    b([si['b']])