我正在尝试使用map来避免Python中的循环以获得更好的性能。我的代码是
def fun(s):
result = []
for i in range(len(s)-1):
if (s[i:i+2]=="ab"):
result.append(s[:i]+"cd"+s[i+2:])
return result
我对该功能的猜测是:
def fun(s):
return map(lambda s : s[:i]+"cd"+s[i+2:] if s[i:i+2]=="ab", s)
但是,在这种情况下,我不知道如何将i与s关联...而且上面的函数在语法上是错误的。 有人可以帮忙吗?
----------------------------------------------- --------添加说明---------------------------------------- --------------- 很多人都很困惑我为什么这样做。这个想法只来自Python performance document(参见循环部分)和Guido's article。我只是在学习。
非常感谢@gboffi,完美而又整洁的答案!
答案 0 :(得分:1)
我用两个辅助定义编写了这个函数,但是如果你想要的话你可以把它写成一个衬里,
def fun(s):
substitute = lambda i: s[:i]+'cd'+s[i+2:]
match = lambda i: s[i:i+2]=='ab'
return map(substitute, filter(match, range(len(s)-1)))
它的工作原理是使用s[i:i+2]
创建'ab'
匹配filter
的索引列表,并仅为匹配的索引映射字符串替换函数。
很明显,由于在每次调用时编译lambdas都会产生很大的开销,但幸运的是很容易测试这个hypotesis
In [41]: def fun(s):
result = []
for i in range(len(s)-1):
if (s[i:i+2]=="ab"):
result.append(s[:i]+"cd"+s[i+2:])
return result
....:
In [42]: def fun2(s):
substitute = lambda i: s[:i]+'cd'+s[i+2:]
match = lambda i: s[i:i+2]=='ab'
return map(substitute, filter(match, range(len(s)-1)))
....:
In [43]: %timeit fun('aaaaaaabaaaabaaabaaab')
100000 loops, best of 3: 2.38 µs per loop
In [44]: %timeit fun2('aaaaaaabaaaabaaabaaab')
100000 loops, best of 3: 3.74 µs per loop
In [45]: %timeit fun('aaaaaaabaaaabaaabaaab'*1000)
10 loops, best of 3: 33.7 ms per loop
In [46]: %timeit fun2('aaaaaaabaaaabaaabaaab'*1000)
10 loops, best of 3: 33.8 ms per loop
In [47]:
对于短字符串,map
版本慢50%,而对于非常长的字符串,时间渐近相等......
答案 1 :(得分:0)
首先,我不认为地图比for循环具有性能优势。 如果's'很大,那么您可以使用xrange而不是范围https://docs.python.org/2/library/functions.html#xrange
第二张地图无法过滤元素,它只能将它们映射到新值。 您可以使用理解而不是for循环,但我认为您也不会获得性能优势。