This post has been de-listed
It is no longer included in search results and normal feeds (front page, hot posts, subreddit posts, etc). It remains visible only via the author's post history.
ranges = [range(2), range(4), range(1)]
# I want to map a function onto the inner iterables. In this case, str.
list_comps = [[str(n) for n in r] for r in ranges]
gen_exps = ((str(n) for n in r) for r in ranges)
maps = map(lambda r: map(str, r), ranges) # Is there a better way?
expected = [['0', '1'], ['0', '1', '2', '3'], ['0']]
# Test
for mapped in [list_comps, gen_exps, maps]:
actual = list(map(list, mapped))
assert expected == actual, actual
Edit: I'm going for a generator of generators. I'd rather not precompute into a list/tuple for memory and shortcutting.
Edit2: Summary for people of the future.(map(str, r) for r in ranges)
is my new favorite. It's from this comment by /u/MKuranowski. There's also map(map, repeat(str), ranges).
I realized this is just a specific case of a more general problem: that I love map for functions with one argument and dislike map for functions with more than one argument.
numbers = ['1', '2', '3']
sum(map(int, numbers)) # I like that a lot
sum(int(n) for n in numbers)) # I like that less.
On the generator expression, it's the n
that bothers me. It feels like that variable isn't really do anything. Things change when the function needs more than one variable.
bins = ['0', '1', '101]
sum(map(lambda n: int(n, base=2), bins)) # meh
sum(int(n, base=2) for n in bins)) # better
Now that n
has meaning. It's showing that it's the first argument to int
. Multiple iterables for arguments is interesting.
bases = [2, 3, 4]
exponents = [0, 1, 2]
sum(map(pow, bases, exponents))
sum(pow(a, b) for a, b in zip(bases, exponents))
If they're already in tuples, then I think itertools.starmap
wins.
zipped = list(zip(bases, exponents))
sum(starmap(pow, zipped))
sum(pow(*x) for x in zipped)
You can treat a repeated argument like an iterable with itertools.repeat
. This reminds me of writing Clojure.
bins = ['0', '1', '101]
sum(map(int, bins, repeat(2))
Now back to the original idea. map
is a function with multiple arguments. So it's not the best candidate as a function to pass to map
. Instead, we end up mixing genexps and maps. I don't have a tiny example in mind for what to use this generator of generators for, so it won't be passed to anything else like in the examples above.
ranges = [range(2), range(4), range(1)]
(map(str, r) for r in ranges)
But after writing all this out, I may just go full functional.
map(map, repeat(str), ranges)
And as a random side-note, I just realized you can use itertools.cycle
and map
to change arguments based on the modulo of the index.
from operator import add
map(add, 'XYZ', cycle('AB')) # -> ('XA', 'YB', 'ZA')
Subreddit
Post Details
- Posted
- 3 years ago
- Reddit URL
- View post on reddit.com
- External URL
- reddit.com/r/learnpython...