Question

I'm wondering what's happening when I execute this code and also if there is a better way to accomplish the same task. Is a list of lists being made in memory to preform the sort, and then bar is assigned to be an iterator of foo.values()? Or possibly foo.values() is sorted in the allotted dictionary memory space (seems unlikely)?

Imagine the first value in the list, the integer, refers to a line number in a file. I want to open the file and update only the lines referenced in the foo.values() lists with the rest of the data in the list (EG update line 1 with strings '123' and '097').

from itertools import imap

>>> foo = {'2134':[1, '123', '097'], '6543543':[3, '1'], '12315':[2, '454']}
>>> bar = imap([].sort(), foo.values())

Thanks~

Was it helpful?

Solution

First, you're passing [].sort(), which is just None, as the first argument to imap, meaning it's doing nothing at all. As the docs explain: "If function is set to None, then imap() returns the arguments as a tuple."

To pass a callable to a higher-order function like imap, you have to pass the callable itself, not call it and pass the result.

Plus, you don't want [].sort here; that's a callable with no arguments that just sorts an empty list, which is useless.

You probably wanted list.sort, the unbound method, which is a callable with one argument that will sort whatever list it's given.


So, if you did that, what would happen is that you'd creating an iterator that, if you iterated it, would generate a bunch of None values and, as a side effect, sort each list in foo.values(). No new lists would be created anywhere, because list.sort mutates the list in-place and returns None.

But since you don't ever iterate it anyway, it hardly matters what you put into imap; what it actually does is effectively nothing.


Generally, abusing map/imap/comprehensions/etc. for side-effects of the expressions is a bad idea. An iterator that generates useless values, but that you have to iterate anyway, is a recipe for confusion at best.

The simple thing to do here is to just use a loop:

for value in foo.values():
    value.sort()

Or, instead of sorting in-place, generate new sorted values:

bar = imap(sorted, foo.values())

Now, as you iterate bar, each list will be sorted and given to you, so you can use it. If you iterate this, it will generate a sorted list in memory for each list… but only one will ever be alive at a time (unless you explicitly stash them somewhere).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top