简体   繁体   English

Python怪异涉及map和reduce

[英]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: 当我在strxo上更改final elsereturn str(n)而不是return "_"我得到:

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 _ : 问题在于,最内部的reduce函数(作用在子列表上的那个函数)总是将第二个参数转换为_

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

So, on the last element of that reduce, b is __ , which gets turned into _ ! 因此,在该reduce的最后一个元素上, b__ ,它变成_

You want to map strxo onto everything first, and then reduce using concatenation. strxostrxo 映射到所有内容, 然后再减少使用串联。

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 . 注意,我删除了对list不必要的调用。

But more importantly, stop using reduce and the concatenation operator to join strings! 但更重要的是, 停止使用reduce和串联运算符来连接字符串!

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). 更重要的是,你应该只使用列表内涵 ,这是突出地功能结构(Python从哈斯克尔偷来的,顺便说一句)。 It is frequently more readable than map + lambda : 它通常比map + lambda更具可读性:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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