I often avoid me to write posts like this but I\'m new in python 3.4 and I need a help with this code.
Suppose we have the following list:
v = [ [ x,
I agree with Mike that map(lambda
is silly. In this case, '{}{}'.format
pretty much does the job your lambda is supposed to do, so you can use that instead:
starmap('{}{}'.format, v)
That uses itertools.starmap. If you want to use map
, you can do it like this:
map('{}{}'.format, *zip(*v))
But really I'd just do
(c + str(n) for c, n in v)
Edit: A comparison of map+lambda vs generator expression, showing that the latter is shorter, clearer, more flexible (unpacking), and faster:
>>> from timeit import timeit
>>> r = range(10000000)
>>> timeit(lambda: sum(map(lambda xy: xy[0]+xy[1], zip(r, r))), number=1)
7.221420832748007
>>> timeit(lambda: sum(x+y for x, y in zip(r, r)), number=1)
5.192609298897533
>>> timeit(lambda: sum(map(lambda x: 2*x, r)), number=1)
5.870139625224283
>>> timeit(lambda: sum(2*x for x in r), number=1)
4.4056527464802
>>> r = range(10)
>>> timeit(lambda: sum(map(lambda xy: xy[0]+xy[1], zip(r, r))), number=1000000)
7.047922363577214
>>> timeit(lambda: sum(x+y for x, y in zip(r, r)), number=1000000)
4.78059718055448
You could use another list comprehension:
>>> [''.join((x, str(y))) for x, y in v]
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']
If you don't need v
, you can do in the first list comprehension:
>>> [''.join((x, str(y))) for x in ['a','b','c'] for y in range(1,5)]
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']
lambda (x, y): ''.join(x,y)
isn't legal Python 3. Iterable unpacking of arguments was removed. If you actually ran the code you showed on the version you mentioned, you would have gotten a syntax error, not the error you showed.
If you did indeed have a list as you describe, not the one you actually made, you would need to give str.join
one iterable argument, not 2 arguments, so lambda (x, y): ''.join([x,y])
(which is similar to the code you showed but not legal Python 3) or, more simply, lambda x_y: ''.join(x_y)
That won't work for you, though, because str.join
takes an iterable of strings, and the resulting list of lists in your case is [ ['a', 1], ['a',2], ... ]
, not [ ['a', '1'], ['a','2'], ... ]
. You can't join a string and a number this way. (Which is fine, since str.join
isn't even the right tool for the job.)
Using map
+lambda
is always silly. Just use a generator expression in all situations you might use map
+lambda
See the following examples (I used list comprehensions instead of generator expressions so we'd get useful reprs):
py> v = [ [ x, y ] for x in ['a','b','c'] for y in range(1,5) ]
py> [''.join([let, num]) for let, num in v]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
TypeError: sequence item 1: expected str instance, int found
py> ['{}{}'.format(let, num) for let, num in v]
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']
You can do:
>>> list(map(lambda x: ''.join(map(str, x)), v))
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']
This executes the function lambda x: ''.join(map(str, x))
for each element in v
. An element in v
is a list with one string and one integer as values. This means x
, as received by the lambda
function, is a list with those two values.
We then need to ensure all values in that list are strings before passing them to join()
. This means we'll call map(str, x)
to turn all values in the sublist x
into strings (['a', 1]
becomes ['a', '1']
). We can then join them by passing the result of that to ''.join(...)
(['a', '1']
becomes ['a1']
). This is done for each list in v
so this gives us the desired result.
The result of map
is a so-called mapobject
in Python 3.x so we wrapped everything in a list()
call to end up with a list.
Also, a list comprehension is arguably more readable here:
>>> [x[0] + str(x[1]) for x in v]
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']
If you just have a set amount of elements to join you can use str.format:
print(list(map(lambda x: "{}{}".format(*x) , v)))
['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4']
You can also do it for any amount of elements using "{}" * len(x)
:
print(list(map(lambda x: ("{}" * len(x)).format(*x) , v)))
*x
unpacks the sequence, "{}" * len(x)
creates a {}
for each element in each sublist.
Or unpack in a list comp:
print([ "{}{}".format(*x) for x in v])