检查sPython 中的字符串只包含一个字符的有效方法是什么'A'?像all_equal(s, 'A')这样的东西会像这样:
all_equal("AAAAA", "A") = True
all_equal("AAAAAAAAAAA", "A") = True
all_equal("AAAAAfAAAAA", "A") = False
Run Code Online (Sandbox Code Playgroud)
两种看似效率低下的方法是:首先将字符串转换为列表并检查每个元素,然后再使用正则表达式.是否有更有效的方法,或者这些是Python中最好的方法?谢谢.
Ell*_*ioh 113
这是迄今为止最快的,比偶数快几倍count(),只是时间与优秀的mgilson定时套件:
s == len(s) * s[0]
Run Code Online (Sandbox Code Playgroud)
这里所有的检查都是在Python C代码中完成的,它只是:
字符串越长,时间奖励越大.但是,正如mgilson所写,它会创建一个字符串的副本,所以如果你的字符串长度是数百万个符号,它可能会成为一个问题.
正如我们从时序结果中看到的,通常,解决任务的最快方法不会为每个符号执行任何Python代码.但是,该set()解决方案还完成了Python库C代码中的所有工作,但它仍然很慢,可能是因为通过Python对象接口操作字符串.
UPD:关于空字符串案例.如何处理它在很大程度上取决于任务.如果任务是"检查字符串中的所有符号是否相同",s == len(s) * s[0]则是有效答案(没有符号表示错误,异常正常).如果任务是"检查是否只有一个唯一符号",则空字符串应该给我们False,答案是s and s == len(s) * s[0],或者bool(s) and s == len(s) * s[0]如果您更喜欢接收布尔值.最后,如果我们将任务理解为"检查是否没有不同的符号",则空字符串的结果为True,答案为not s or s == len(s) * s[0].
mgi*_*son 42
>>> s = 'AAAAAAAAAAAAAAAAAAA'
>>> s.count(s[0]) == len(s)
True
Run Code Online (Sandbox Code Playgroud)
这不会短路.一个做短路的版本是:
>>> all(x == s[0] for x in s)
True
Run Code Online (Sandbox Code Playgroud)
但是,我觉得由于优化的C实现,非短路版本可能在某些字符串上表现更好(取决于大小等)
这是一个简单的timeit脚本来测试发布的其他一些选项:
import timeit
import re
def test_regex(s,regex=re.compile(r'^(.)\1*$')):
return bool(regex.match(s))
def test_all(s):
return all(x == s[0] for x in s)
def test_count(s):
return s.count(s[0]) == len(s)
def test_set(s):
return len(set(s)) == 1
def test_replace(s):
return not s.replace(s[0],'')
def test_translate(s):
return not s.translate(None,s[0])
def test_strmul(s):
return s == s[0]*len(s)
tests = ('test_all','test_count','test_set','test_replace','test_translate','test_strmul','test_regex')
print "WITH ALL EQUAL"
for test in tests:
print test, timeit.timeit('%s(s)'%test,'from __main__ import %s; s="AAAAAAAAAAAAAAAAA"'%test)
if globals()[test]("AAAAAAAAAAAAAAAAA") != True:
print globals()[test]("AAAAAAAAAAAAAAAAA")
raise AssertionError
print
print "WITH FIRST NON-EQUAL"
for test in tests:
print test, timeit.timeit('%s(s)'%test,'from __main__ import %s; s="FAAAAAAAAAAAAAAAA"'%test)
if globals()[test]("FAAAAAAAAAAAAAAAA") != False:
print globals()[test]("FAAAAAAAAAAAAAAAA")
raise AssertionError
Run Code Online (Sandbox Code Playgroud)
在我的机器(OS-X 10.5.8,酷睿2,python2.7.3)与这些做作(短)的字符串,str.count吸烟set和all,和节拍str.replace受了一点,但被排挤出去str.translate,并strmul是目前在由佳缘的铅:
WITH ALL EQUAL
test_all 5.83863711357
test_count 0.947771072388
test_set 2.01028490067
test_replace 1.24682998657
test_translate 0.941282987595
test_strmul 0.629556179047
test_regex 2.52913498878
WITH FIRST NON-EQUAL
test_all 2.41147494316
test_count 0.942595005035
test_set 2.00480484962
test_replace 0.960338115692
test_translate 0.924381017685
test_strmul 0.622269153595
test_regex 1.36632800102
Run Code Online (Sandbox Code Playgroud)
不同系统和不同字符串之间的时间可能略有差异(甚至显着不同),因此值得研究一下您计划传递的实际字符串.
最终,如果你all足够了,并且你的字符串足够长,你可能想要考虑那个.这是一个更好的算法...我会避免set解决方案,因为我没有看到任何情况下它可能会击败count解决方案.
如果内存可能是一个问题,你需要避免str.translate,str.replace并且strmul因为那些创建了第二个字符串,但这些日子通常不是问题.
Mar*_*ers 12
尝试使用内置函数all:
all(c == 'A' for c in s)
Run Code Online (Sandbox Code Playgroud)
如果需要检查字符串中的所有字符是否相同并且是否等于给定字符,则需要删除所有重复项并检查最终结果是否等于单个字符.
>>> set("AAAAA") == set("A")
True
Run Code Online (Sandbox Code Playgroud)
如果您想查找是否有重复,只需检查长度
>>> len(set("AAAAA")) == 1
True
Run Code Online (Sandbox Code Playgroud)