How do I make Maps and lambdas work with a matrix in python 3.4?

前端 未结 5 1957
有刺的猬
有刺的猬 2020-12-20 07:58

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,         


        
相关标签:
5条回答
  • 2020-12-20 08:30

    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
    
    0 讨论(0)
  • 2020-12-20 08:31

    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']
    
    0 讨论(0)
  • 2020-12-20 08:34
    1. 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.

    2. 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)

    3. 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.)

    4. 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']
    
    0 讨论(0)
  • 2020-12-20 08:37

    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']
    
    0 讨论(0)
  • 2020-12-20 08:45

    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])
    
    0 讨论(0)
提交回复
热议问题