快速和pythonic的方式来找出一个字符串是一个回文
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速和pythonic的方式来找出一个字符串是一个回文相关的知识,希望对你有一定的参考价值。
[编辑:有人指出我使用了不正确的palindrom概念,现在我已经编辑了正确的功能。我在第一个和第三个例子中也做了一些优化,其中for语句一直到它达到字符串的一半]
我已经为一个检查字符串是否为回文的方法编写了三个不同的版本。该方法实现为类“str”的扩展
该方法还将字符串转换为小写,并删除所有准时和空格。哪一个更好(更快,pythonic)?
以下是方法:
1)这是我想到的第一个解决方案:
def palindrom(self):
lowerself = re.sub("[ ,.;:?!]", "", self.lower())
n = len(lowerself)
for i in range(n//2):
if lowerself[i] != lowerself[n-(i+1)]:
return False
return True
我认为这个更快,因为没有字符串的转换或反转,并且for语句在第一个不同的元素处断开,但我不认为这是一种优雅和pythonic的方式
2)在第二个版本中,我使用在stackoverflow上创建的解决方案进行转换(使用高级切片字符串[:: - 1])
# more compact
def pythonicPalindrom(self):
lowerself = re.sub("[ ,.;:?!]", "", self.lower())
lowerReversed = lowerself[::-1]
if lowerself == lowerReversed:
return True
else:
return False
但我认为切片和字符串之间的比较会使这个解决方案变慢。
3)我想到的第三个解决方案,使用迭代器:
# with iterator
def iteratorPalindrom(self):
lowerself = re.sub("[ ,.;:?!]", "", self.lower())
iteratorReverse = reversed(lowerself)
for char in lowerself[0:len(lowerself)//2]:
if next(iteratorReverse) != char:
return False
return True
我认为第一种解决方案更优雅,第二种解决方案效率更高
所以,我决定只是timeit
,并找到哪一个是最快的。请注意,最终功能是您自己的pythonicPalindrome
的更清洁版本。它的定义如下:
def palindrome(s, o):
return re.sub("[ ,.;:?!]", "", s.lower()) == re.sub("[ ,.;:?!]", "", o.lower())[::-1]
Methodology
我为每个函数运行了10个不同的测试在每次测试运行中,函数被调用10000次,参数为self="aabccccccbaa", other="aabccccccbaa"
。结果可以在下面找到。
palindrom iteratorPalindrome pythonicPalindrome palindrome
1 0.131656638 0.108762937 0.071676536 0.072031984
2 0.140950052 0.109713793 0.073781851 0.071860462
3 0.126966087 0.109586756 0.072349792 0.073776719
4 0.125113136 0.108729573 0.094633969 0.071474645
5 0.130878159 0.108602964 0.075770395 0.072455015
6 0.133569472 0.110276694 0.072811747 0.071764222
7 0.128642812 0.111065438 0.072170571 0.072285204
8 0.124896702 0.110218949 0.071898959 0.071841214
9 0.123841905 0.109278358 0.077430437 0.071747112
10 0.124083576 0.108184210 0.080211147 0.077391086
AVG 0.129059854 0.109441967 0.076273540 0.072662766
STDDEV 0.005387429 0.000901370 0.007030835 0.001781309
看起来你的pythonicPalindrome
的清洁版略快,但两种功能都明显超出了替代品。
您似乎想知道代码块的执行时间并进行比较。
您可以使用timeit模块。
这是一个快速的方法:
import timeit
start = timeit.default_timer()
#Your code here
stop = timeit.default_timer()
print stop - start
阅读更多:
你也可以计算这个不使用re的单行程,但是反之亦然:
def isPalindrom(self):
return all(i==j for i, j in itertools.zip_longest((i.lower() for i in self if i not in " ,.;:?!"), (j.lower() for j in self[::-1] if j not in " ,.;:?!")))
或者,更详细地解释:
def isPalindrom(self):
#using generators to not use memory
stripped_self = (i.lower() for i in self if i not in " ,.;:?!")
reversed_stripped_self = (j.lower() for j in self[::-1] if j not in " ,.;:?!")
return all(self_char==reversed_char for self_char, reversed_char in itertools.zip_longest(stripped_self, reversed_stripped_self))
回想一下,filter
适用于字符串:
>>> st="One string, with punc. That also needs lowercase!"
>>> filter(lambda c: c not in " ,.;:?!", st.lower())
'onestringwithpuncthatalsoneedslowercase'
因此,您的测试可以是一个功能明显的单线程:
>>> str
'!esacrewol sdeen osla tahT .cnup htiw ,gnirts enO'
>>> filter(lambda c: c not in " ,.;:?!", st.lower())==filter(lambda c: c not in " ,.;:?!", str.lower()[::-1])
True
或者,如果您要使用正则表达式,只需使用惯用的str[::-1]
反转结果:
>>> "123"[::-1]
'321'
>>> re.sub(r'[ ,.;:?!]', '', st.lower())==re.sub(r'[ ,.;:?!]', '', str.lower())[::-1]
True
最快的可能是使用string.tranlate删除字符:
>>> import string
>>> string.translate(st, None, " ,.;:?!")
'OnestringwithpuncThatalsoneedslowercase'
>>> string.translate(st, None, " ,.;:?!")==string.translate(str, None, " ,.;:?!")[::-1]
True
当我们传递一个单词时,它检查它是否可以反转,如果它可以被反转,则打印“这是一个回文”。或者“这不是回文”
def reverse(word):
x = ''
for i in range(len(word)):
x += word[len(word)-1-i]
return x
word = input('give me a word:\n')
x = reverse(word)
if x == word:
print('This is a Palindrome')
else:
print('This is NOT a Palindrome')
以上是关于快速和pythonic的方式来找出一个字符串是一个回文的主要内容,如果未能解决你的问题,请参考以下文章