эффективно проверка, что строка состоит из одного символа в Python

Что эффективный путь состоит в том, чтобы проверить что строка s в Python состоит всего из одного символа, сказать 'A'? Что-то как all_equal(s, 'A') который вел бы себя как это:

all_equal("AAAAA", "A") = True

all_equal("AAAAAAAAAAA", "A") = True

all_equal("AAAAAfAAAAA", "A") = False

Два на вид неэффективных пути были бы к: сначала преобразуйте строку в список и проверьте каждый элемент, или второй для использования регулярного выражения. Есть ли более эффективные пути, или это лучшее, может сделать в Python?Спасибо.

62
задан 23 September 2016 в 12:48

8 ответов

Это является безусловно самым быстрым, несколько раз быстрее, чем даже count(), только время это с тем превосходным синхронизация mgilson комплекта :

s == len(s) * s[0]

Здесь вся проверка сделана в коде Python C который просто:

  • выделяет len (s) символы;
  • заливки пространство с первым символом;
  • сравнивает две строки.

, Чем дольше строка, тем больше премия времени. Однако как 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].

111
ответ дан 31 October 2019 в 13:10
>>> 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, поскольку они создают вторую строку, но это не обычно беспокойство в эти дни.

42
ответ дан 31 October 2019 в 13:10

Вы могли преобразовать в набор и проверку, там только один участник:

len(set("AAAAAAAA"))
16
ответ дан 31 October 2019 в 13:10

Попытайтесь использовать встроенную функцию all :

all(c == 'A' for c in s)
12
ответ дан 31 October 2019 в 13:10

Добавление другого решения этой проблемы

>>> not "AAAAAA".translate(None,"A")
True
6
ответ дан 31 October 2019 в 13:10

Если необходимо проверить, являются ли все символы в строке тем же, и равно данному символу, необходимо удалить все дубликаты и проверку, если конечный результат равняется отдельному символу.

>>> set("AAAAA") == set("A")
True

В случае, если Вы требуете найти, существует ли какой-либо дубликат, просто проверьте длину

>>> len(set("AAAAA")) == 1
True
5
ответ дан 31 October 2019 в 13:10

Интересные ответы до сих пор. Вот другой:

flag = True
for c in 'AAAAAAAfAAAA':
    if not c == 'A': 
        flag = False
        break

единственное преимущество я могу думать к моему, то, что оно не должно пересекать всю строку, если оно находит непоследовательный символ.

3
ответ дан 31 October 2019 в 13:10
not len("AAAAAAAAA".replace('A', ''))
2
ответ дан 31 October 2019 в 13:10

Другие вопросы по тегам:

Похожие вопросы: