Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用lambda函数实现多字符串替换()_Python - Fatal编程技术网

Python 使用lambda函数实现多字符串替换()

Python 使用lambda函数实现多字符串替换(),python,Python,我已经找到了很多解决方案,它们正是我在没有lambda的情况下想要做的…但我今天正在学习lambda 我有一个字符串stri,我正在尝试替换stri中存储在字典中的一些字符 bad\u chars={“\newline”:“\n”:“\b”:“\f”:“\r”:“\t”:“\v”:“\0x00”:”}然后我想打印出所有这些丑陋的字符。我当前的代码打印的stri多次 format\u ught=lambda stri:[stri.替换坏字符中i,j的(i,j)] 有没有办法让它只打印一次,并且只使

我已经找到了很多解决方案,它们正是我在没有lambda的情况下想要做的…但我今天正在学习lambda

我有一个字符串
stri
,我正在尝试替换
stri
中存储在字典中的一些字符

bad\u chars={“\newline”:“\n”:“\b”:“\f”:“\r”:“\t”:“\v”:“\0x00”:”}
然后我想打印出所有这些丑陋的字符。我当前的代码打印的
stri
多次

format\u ught=lambda stri:[stri.替换坏字符中i,j的(i,j)]


有没有办法让它只打印一次,并且只使用一个lambda函数?

您不应该生成一个值列表。您的代码生成一个值列表,其中原始文本只替换了一个字符(每个版本一个字符)。而是对一个条目的结果进行操作,并将其传递给下一个条目。这几乎就是reduce所做的:

replaced = reduce(lambda stri, r: stri.replace(r[0], r[1]), bad_chars.iteritems(), original)
这大致相当于:

stri.replace(r0[0], r0[1]).replace(r1[0], r1[1]).replace(...)

其中,
r0..rn
是来自
bad_chars.iteritems()

的值,您不能很容易地做到这一点,如果可以的话,
lambda
函数仍然不是为您的用例设计的

使用常规的
for
循环语句可以进行多次类似的替换,而
lambda
仅限于一个表达式。如果必须使用函数,请使用普通函数–它完全等同于lambda函数,但不限于单个表达式

如果您确实必须知道如何在单个表达式中执行此操作,则有三种选择:

1) 如果使用
unicode
字符串(或Python 3),并将坏的子字符串限制为单个字符(即删除
“\newline”
),则可以使用
unicode.translate
方法

bad_chars = {u"\n": u" ", u"\b": u" ", u"\f": u" ", u"\r": u" ", u"\t": u" ", u"\v": u" ", u"\x00": u" "}
bad_chars_table = dict((ord(k), v) for k, v in bad_chars.iteritems())
translator = lambda s: s.translate(bad_chars_table)
print translator(u"here\nwe\tgo")
2) 使用正则表达式:

   translator = lambda s: re.sub(r'[\n\b\f\r\t\v\x00]', ' ', s)
3) 您可以使用
reduce
,它可以使用二进制操作来减少序列,基本上是用当前值和序列中的一个元素重复调用两个参数的函数来获得下一个值

translator = lambda s: reduce(lambda x, (from, to): x.replace(from, to), bad_chars.iteritems(), s)
如您所见,最后一个解决方案比以下解决方案更难理解:

def translator(s):
    for original, replacement in bad_chars.iteritems():
        s = s.replace(original, replacement)
    return s

这两种解决方案的作用是相同的。通常最好是为目的而不是为手段而规划。对于任意问题,一个可理解的单表达式解决方案根本不存在。

如果您真的想,您可以在其中强制使用lambda函数:

print ''.join(map(lambda x: bad_chars.get(x, x), stri))
但实际上这里绝对不需要使用lambda函数。您所需要的只是:

print ''.join(bad_chars.get(x, x) for x in stri)
此解决方案也是线性时间(即O(n)),而所有其他解决方案都可能是二次的,因为它们涉及扫描整个字符串以替换每个值O(n*m),其中m是
坏字符的大小

例如:

bad_chars= {"\newline":" ","\n": " ", "\b":" ", "\f":" ", "\r":" ", "\t":" ", "\v":" ", "\0x00":" "}
stri = "a \b string\n with \t lots of \v bad chars"
print ''.join(bad_chars.get(x, x) for x in stri)
乌普图特:

a   string  with   lots of   bad chars

为什么您的代码会多次打印stri?调用lambda函数后打印一次。它为字典中的每个项目打印一次
stri
,最多更改一个字符(看起来它在仅对字符串进行一次更改后,每次迭代for循环时都会打印一次)。
“\newline”
是坏字符
'\n'
-你已经替换了它-后面是
'ewline'
-这些都是不应该被替换的普通字母。这看起来不错…但我还是迷路了。我会把你的代码弄乱一会儿,看看我能不能把它弄明白。谢谢,如果你想让它成为一个lambda表达式,只需在前面加上
lambda original,bad_chars:
,并称之为
replaced(original,bad_chars)
。Python 2字符串也有
translate
。最后编写程序的好建议。我会把那个写下来的。我将在一天之内读完。非常强大的解决方案,谢谢。我想我应该读更多关于什么时候应该使用lambda函数而不是试图解决任意问题的内容。这很好,只是因为它与其他回答者(和我)的想法大不相同。我希望我能投两次票。它甚至可能有很好的性能,因为dict查找很快,并且只遍历字符串一次。您可以通过执行
get=bad\u chars.get
来加快速度,这样您就不必每次都执行
getattr
步骤。