Что эффективный путь состоит в том, чтобы проверить что строка s
в Python состоит всего из одного символа, сказать 'A'
? Что-то как all_equal(s, 'A')
который вел бы себя как это:
all_equal("AAAAA", "A") = True
all_equal("AAAAAAAAAAA", "A") = True
all_equal("AAAAAfAAAAA", "A") = False
Два на вид неэффективных пути были бы к: сначала преобразуйте строку в список и проверьте каждый элемент, или второй для использования регулярного выражения. Есть ли более эффективные пути, или это лучшее, может сделать в Python?Спасибо.
Это является безусловно самым быстрым, несколько раз быстрее, чем даже count()
, только время это с тем превосходным синхронизация mgilson комплекта :
s == len(s) * s[0]
Здесь вся проверка сделана в коде Python C который просто:
, Чем дольше строка, тем больше премия времени. Однако как mgilson записи, это создает копию строки, поэтому если Ваша длина строки является многими миллионами символов, это может стать проблемой.
, Как мы видим от синхронизации результатов, обычно самые быстрые способы решить задачу не выполняют кода Python для каждого символа. Однако set()
решение также делает все задание в коде C библиотеки Python, но это все еще медленно, вероятно, из-за операционной строки через интерфейс объекта Python.
UPD: Относительно случая пустой строки. Что сделать с ним, сильно зависит от задачи. Если задачей является "проверка, если все символы в строке являются тем же", s == len(s) * s[0]
действительный ответ (никакие символы не означают ошибки, и исключение в порядке). Если задачей является "проверка, если существует точно один уникальный символ", пустая строка должна дать нам Ложь, и ответ s and s == len(s) * s[0]
, или bool(s) and s == len(s) * s[0]
, если Вы предпочитаете получать булевы значения. Наконец, если мы понимаем задачу как "проверка, при отсутствии различных символов", результат для пустой строки Правда, и ответ not s or s == len(s) * s[0]
.
>>> s = 'AAAAAAAAAAAAAAAAAAA'
>>> s.count(s[0]) == len(s)
True
Это не срывает. Версия, которая действительно закорачивает, была бы:
>>> all(x == s[0] for x in s)
True
Однако у меня есть чувство, что должный оптимизированная реализация C, не срывающая версия будет, вероятно, работать лучше на некоторых строках (в зависимости от размера, и т.д.)
<час> Вот простое timeit
сценарий для тестирования некоторых из других отправленных опций:
import timeit
import re
def test_regex(s,regex=re.compile(r'^(.)\1* На моей машине (OS X 10.5.8, core2duo, 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
синхронизации могли быть немного (или даже значительно?) отличающийся между различными системами и с различными строками, так, чтобы стоило бы изучить с фактической строкой, Вы - планирование передачи.
В конечном счете, если Вы поражаете лучший случай для [1 111] достаточно, и Ваши строки, достаточно длинны, Вы могли бы хотеть полагать что один. Это - лучший алгоритм... Я избежал бы set
решение хотя, поскольку я не вижу случая, где это могло возможно сбить count
решение.
, Если память могла бы быть проблемой, необходимо будет избежать str.translate
, str.replace
и strmul
, поскольку они создают вторую строку, но это не обычно беспокойство в эти дни.
)):
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
На моей машине (OS X 10.5.8, core2duo, 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
синхронизации могли быть немного (или даже значительно?) отличающийся между различными системами и с различными строками, так, чтобы стоило бы изучить с фактической строкой, Вы - планирование передачи.
В конечном счете, если Вы поражаете лучший случай для [1 111] достаточно, и Ваши строки, достаточно длинны, Вы могли бы хотеть полагать что один. Это - лучший алгоритм... Я избежал бы set
решение хотя, поскольку я не вижу случая, где это могло возможно сбить count
решение.
, Если память могла бы быть проблемой, необходимо будет избежать str.translate
, str.replace
и strmul
, поскольку они создают вторую строку, но это не обычно беспокойство в эти дни.
Вы могли преобразовать в набор и проверку, там только один участник:
len(set("AAAAAAAA"))
Попытайтесь использовать встроенную функцию all
:
all(c == 'A' for c in s)
Добавление другого решения этой проблемы
>>> not "AAAAAA".translate(None,"A")
True
Если необходимо проверить, являются ли все символы в строке тем же, и равно данному символу, необходимо удалить все дубликаты и проверку, если конечный результат равняется отдельному символу.
>>> set("AAAAA") == set("A")
True
В случае, если Вы требуете найти, существует ли какой-либо дубликат, просто проверьте длину
>>> len(set("AAAAA")) == 1
True
Интересные ответы до сих пор. Вот другой:
flag = True
for c in 'AAAAAAAfAAAA':
if not c == 'A':
flag = False
break
единственное преимущество я могу думать к моему, то, что оно не должно пересекать всю строку, если оно находит непоследовательный символ.