Python怪异涉及map和reduce

时间:2018-08-09 22:28:28

标签: python arrays python-3.x functional-programming off-by-one

对不起,标题模糊,但我真的不知道这是怎么回事。

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)

所需的输出:

___
___
___

实际输出:

__
__
__

当我将else上的最终strxo更改为return str(n)而不是return "_"时,我得到:

000
000
000

这是我期望的形状,但我想替换那些零。是什么原因造成的?

1 个答案:

答案 0 :(得分:6)

问题在于,最内部的reduce函数(作用在子列表上的那个函数)总是将第二个参数转换为_

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

因此,在减少的最后一个元素上,b__,它变成了_

您想先映射 strxo到所有内容上,然后然后使用串联来减少。

所以你想要这样的东西:

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

请注意,我删除了对list的不必要的调用。

但更重要的是,停止使用reduce和串联运算符来连接字符串!

它不必要地冗长,并且启动效率低(它将具有二次时间复杂度)。

相反,使用:

joinstr = ''.join

这是一个非常好的功能。函数式编程并不意味着“使用映射并尽可能地缩小”。

所以,这里有一些好的函数式编程:

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

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

更好的是,您应该只使用 list comprehensions ,它们是杰出的功能构造(Python从Haskell,btw偷走了它们)。它通常比map + lambda更具可读性:

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