简体   繁体   中英

Python weirdness involving map and reduce

Sorry for the vague title, but I really have no idea what's going on here.

from functools import reduce

arr = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

def strxo(n):
    if (n == -1):
        return "X"
    elif (n == 1):
        return "O"
    else:
        return "_"

def prboard(board):
    print(reduce(lambda x, y: x + "\n" + y, list(map(lambda l: reduce(lambda a, b: strxo(a) + strxo(b), l), board))))

prboard(arr)

Desired output:

___
___
___

Real output:

__
__
__

And when I change the final else on strxo to return str(n) instead of return "_" I get:

000
000
000

Which is what I would expect and the shape I want, but I want to replace those zeroes. What is causing this?

The problem is that your inner most reduce function, the one acting on your sublists, is always turning the second argument to _ :

lambda a, b: strxo(a) + strxo(b)

So, on the last element of that reduce, b is __ , which gets turned into _ !

You want to map strxo onto everything first, and then reduce using concatenation.

So you want something like this:

reduce(lambda x, y: x + "\n" + y, map(lambda l: reduce(lambda a, b: a + b, map(strxo, l)), board))

Note, I removed the unecessary call to list .

But more importantly, stop using reduce and the concatenation operator to join strings!

It is unnecessarily verbose, and it is inefficient to boot (it will have quadratic time complexity).

Instead, use:

joinstr = ''.join

Which is a perfectly fine function. Functional programming doesn't mean "use map and reduce everywhere possible".

So, here's some good functional programming:

joinstr = ''.join
join_newline = '\n'.join

def board_str(board):
    return join_newline(map(lambda l: joinstr(map(strxo,l)), board))

Better yet, you should just use list comprehensions , which are eminently functional constructs (Python stole them from Haskell, btw). It is frequently more readable than map + lambda :

def board_string(board):
    return join_newline([joinstr(map(strxo, l)) for l in board])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM