Force all iterations on an iterable

2019-07-09 03:07发布

I've written a for-loop using map, with a function that has a side-effect. Here's a minimal working example of what I mean:

def someFunc(t):
    n, d = t
    d[n] = str(n)

def main():
    d = {}
    map(somefunc, ((i,d) for i in range(10**3)))
    print(len(d))

So it's clear that someFunc, which is mapped onto the non-negative numbers under 1000, has the side-effect of populating a dictionary, which is later used for something else.

Now, given the way that the above code has been structured, the expected output of print(len(d)) is 0, since map returns an iterator, and not a list (unlike python2.x). So if I really want to see the changes applied to d, then I would have to iterate over that map object until completion. One way I could do so is:

d = {}
for i in map(somefunc, ((i,d) for i in range(10**3))):
    pass

But that doesn't seem very elegant. I could call list on the map object, but that would require O(n) memory, which is inefficient. Is there a way to force a full iteration over the map object?

1条回答
Bombasti
2楼-- · 2019-07-09 03:37

You don't want to do this (run a map() just for the side effects), but there is a itertools consume recipe that applies here:

from collections import deque

deque(map(somefunc, ((i,d) for i in range(10**3))), maxlen=0)

The collections.deque() object, configured to a maximum size of 0, consumes the map() iterable with no additional memory use. The deque object is specifically optimized for this use-case.

查看更多
登录 后发表回答