imap vs map

Arnaud Delobelle arnodel at googlemail.com
Fri Mar 5 17:00:16 EST 2010


mk <mrkafk at gmail.com> writes:

> Hello everyone,
>
> I re-wrote more "slowly" an example at the end of
> http://wordaligned.org/articles/essential-python-reading-list
>
>
> This example finds anagrams in the text file.
>
> ====
> from itertools import groupby, imap
> from operator import itemgetter
>
> from string import ascii_lowercase, ascii_uppercase, punctuation,
> maketrans, translate
>
> data = open(r"c:\temp\words.txt", "rt").read()
>
> trtable = maketrans(ascii_uppercase, ascii_lowercase)
>
> words = translate(data, trtable, deletions = punctuation)
>
> words = list(set(words.split()))
>
> sw = sorted(words, key=sorted)
>
> gb = groupby(sw, sorted)
>
> print map(list, imap(itemgetter(1), gb))
> ===
>
> words.txt:
> ===
> Word Aligned
> three
> space sensitive programming
> Feed Logo tins
> Essential Python post  Reading List
> stop course there
> times isnt
> capes
> ===
>
> Now, when I execute above, it works:
>
> [['capes', 'space'], ['aligned'], ['reading'], ['essential'],
> ['programming'], ['course'], ['feed'], ['word'], ['there', 'three'],
> ['sensitive'], ['times'], ['logo'], ['python'], ['list'], ['isnt',
> tins'], ['stop', 'post']]
>
>
> However, when I change the last line to:
>
> print map(list, map(itemgetter(1), gb))
>
> It stops working:
>
> [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], ['post']]
>
> Why? I was under impression that the only difference between map and
> imap is that imap returns iterator allowing to produce a list, while
> map returns equivalent list?
>
> Regards,
> mk

>From the itertools docs [1]:

     The returned group is itself an iterator that shares the underlying
     iterable with groupby(). Because the source is shared, when the
     groupby() object is advanced, the previous group is no longer
     visible. So, if that data is needed later, it should be stored as a
     list:

     (example follows)

So when you use:

     print map(list, imap(itemgetter(1), gb))

each group is stored as a list *before* the groupby() object is
advanced, so that's ok.

However, when you use:

    print map(list, map(itemgetter(1), gb))

the groupby() object is advanced to the end *before* each group is
stored as a list.  According the the docs quoted above, this renders
each group no longer visible.

It is for the same reason that the following are different:

>>> def foo():
...     for i in range(5):
...         yield lambda: i
... 
>>> map(lambda f: f(), imap(lambda x: x, foo()))
[0, 1, 2, 3, 4]
>>> map(lambda f: f(), map(lambda x: x, foo()))
[4, 4, 4, 4, 4]

Although looking back at it, I don't know if this will help you :)

[1] http://docs.python.org/library/itertools.html#itertools.groupby

-- 
Arnaud



More information about the Python-list mailing list