2011-08-20 23 views
3

我发现吨做什么,我试图做WITHOUT拉姆达......但我学习的λ今天的解决方案的替代()...实现多个字符串中使用lambda函数

我有一个字符串stri,我试图替换stri中的一些字符,这些字符都存储在字典中。

bad_chars={"\newline":" ","\n": " ", "\b":" ", "\f":" ", "\r":" ", "\t":" ", "\v":" ", "\0x00":" "}然后我想打印stri列出所有这些丑陋字符的漂亮和空白。我目前的代码打印的stri很多次。

format_ugly = lambda stri: [ stri.replace(i,j) for i,j in bad_chars.iteritems()]

有没有办法让它打印一次,而且只有1 lambda函数?

+2

为什么你的代码打印'stri'很多很多次?调用lambda函数后打印一次。 –

+0

它为字典中的每个项目打印一次'stri',其中1个字符最多改变了一次(它只是在对字符串进行1次更改后每次迭代我的for循环时都会打印)。 – Rell3oT

+3

'“\ newline”'是坏字符''\ n'' - 您已经替换 - 然后是'ewline' - 这些都是不应该被替换的普通字母。 –

回答

1

你不能那么容易地做到这一点,如果你可以的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 

而且这两种解决方案做同样的事情。最后编程通常更好,而不是手段。对于任意问题,根本不存在可理解的单一表达式解决方案。

+0

Python 2的字符串也有'translate'。 – agf

+0

好的建议,以方案结束。我写下那个。 – Rell3oT

1

您不应该产生值的列表。您的代码会生成一个只包含一个字符的原始文本值列表(每个版本一个)。而是根据一个条目的结果进行操作并将其传递给下一个条目。这差不多就是减少呢:

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..rnbad_chars.iteritems()值。

+0

这看起来不错....但我仍然输了。不妨将你的代码弄糟一会儿,看看我是否全力以赴。谢谢 – Rell3oT

+0

如果你希望它是一个lambda表达式,只需在'lambda original,bad_chars:'的前面加上'replace'(original,bad_chars)'即可。 – agf

2

如果你真的想你可以强制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字典的大小。

例子:

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) 

Ouptut:

a string with lots of bad chars 
+0

哦,我的天啊。我要读取得到。很强大的解决方案,谢谢。我想我应该多读一些关于什么时候应该使用lambda函数而不是试图解决任意问题的问题 – Rell3oT

+1

这是__great__,仅仅因为它和其他答案者(和我)的想法完全不同。我希望我可以两次上调它。它甚至可能具有良好的性能,因为字典查找速度很快,而且只能遍历一次字符串。你可以通过'get = bad_chars.get'来加速它,所以你不必每次都执行'getattr'步骤。 – agf

相关问题