Как проверить, содержит ли строка только символы из заданного набора в python

У меня есть полином, введенный пользователем, и я хочу использовать его только в том случае, если он содержит только символы в строке 1234567890^-+x.

Как я могу проверить, работает это или нет без использования внешних пакетов? Я хочу использовать только встроенные функции Python 2.5.

Я пишу программу, которая работает на любом Mac без внешних пакетов.


person user2658538    schedule 22.12.2013    source источник


Ответы (6)


Вот несколько странных ;-) способов сделать это:

good = set('1234567890^-+x')

if set(input_string) <= good:
    # it's good
else:
    # it's bad

or

if input_string.strip('1234567890^-+x'):
    # it's bad!
else:
    # it's good
person Tim Peters    schedule 22.12.2013
comment
Мне нравится подход, основанный на наборе подмножеств :-) Хочешь timeit попробовать? - person Martijn Pieters; 22.12.2013
comment
@MartijnPieters, не шанс - есть оооочень много способов сделать это, я не хочу тратить полчаса на их организацию ;-) - person Tim Peters; 22.12.2013
comment
@ user2357112, просто потому, что я никогда не могу вспомнить, что именно делает .issuperset(), не глядя :-( Но я сразу понимаю <=, и, как говорит Мартин, в конце концов это одно и то же. .issuperset(), вероятно, медленнее из-за стоимость метода поиска. - person Tim Peters; 22.12.2013
comment
issuperset() — это просто инверсия issubset(); >= к вашему <=. - person Martijn Pieters; 22.12.2013
comment
@MartijnPieters, конечно, но с написанием метода я никогда не могу вспомнить, какой из них <=, а какой >= без поиска. Поэтому я их избегаю. <= и >= для меня очевидны. - person Tim Peters; 22.12.2013
comment
@MartijnPieters: issuperset хотел бы... подождите, видимо, короткого замыкания не происходит. Я думал, что он выполнит тест без создания набора из input_string, но когда я попробовал {0}.issuperset(xrange(1000000000)) несколько секунд назад, он начал потреблять память таким образом, который, кажется, указывает на то, что он превращает ввод в набор. Я думаю, что нет никакого преимущества в производительности. - person user2357112 supports Monica; 22.12.2013

Используйте регулярное выражение:

import re

if re.match('^[-0-9^+x]*$', text):
    # Valid input

Модуль re поставляется с Python 2.5 и является самым быстрым вариантом.

Демо:

>>> re.match('^[-0-9^+x]*$', '1x2^4-2')
<_sre.SRE_Match object at 0x10f0b6780>
person Martijn Pieters    schedule 22.12.2013

  1. Вы можете преобразовать допустимые символы в set, так как наборы предлагают более быстрый поиск
  2. Затем вы можете использовать функцию all, подобную этой

    valid_chars = set("1234567890^-+x")  # Converting to a set
    if all(char in valid_chars for char in input_string):
        # Do stuff if input is valid
    
  3. Мы можем преобразовать входную строку также в набор и проверить, все ли символы во входной строке находятся в допустимом списке.

    valid_chars = set("1234567890^-+x")  # Converting to a set
    if set(input_string).issubset(valid_chars):
        # Do stuff if input is valid
    
person thefourtheye    schedule 22.12.2013
comment
Для этого у наборов есть метод issuperset. - person user2357112 supports Monica; 22.12.2013
comment
@ user2357112 Пожалуйста, проверьте мой ответ сейчас, я использовал issubset - person thefourtheye; 22.12.2013
comment
Это не синтаксис для преобразования строки в набор; вы хотите set("1234567890^-+x"). (Почему я сначала увидел другое?) - person user2357112 supports Monica; 22.12.2013
comment
@user2357112 user2357112 Это называется пониманием множества. - person thefourtheye; 22.12.2013
comment
Нет, это не так. Это литерал набора с 1 элементом. - person user2357112 supports Monica; 22.12.2013
comment
@TimPeters Да, он прав :) Меня всегда путают с этим обозначением :( - person thefourtheye; 22.12.2013

Как насчет того, чтобы просто преобразовать строку в набор и проверить input_set is subset of good_set, как показано ниже:

>>> good_set = set('1234567890^-+x')
>>> input_set1 = set('xajfb123')
>>> input_set2 = set('122-32+x')
>>> input_set1.issubset(good_set)
False
>>> input_set2.issubset(good_set)
True
>>>
person James    schedule 22.12.2013

Еще один способ сделать это, теперь используя string.translate():

>>> import string
>>> all_chars = string.maketrans('', '')
>>> has_only = lambda s, valid_chars: not s.translate(all_chars, valid_chars)
>>> has_only("abc", "1234567890^-+x.")
False
>>> has_only("x^2", "1234567890^-+x.")
True

Это не самый читаемый способ. Он должен быть одним из самых быстрых, если вам это нужно.

person jfs    schedule 22.12.2013
comment
Вместо этого вы можете передать None в качестве первого аргумента translate(). - person Tim Peters; 22.12.2013
comment
У кого-нибудь еще есть Python 2.5, чтобы проверить? LOL ;-) Это работает во всех текущих Python :-) - person Tim Peters; 22.12.2013

person    schedule
comment
min() вряд ли лучшая функция для этой задачи. - person Martijn Pieters; 22.12.2013
comment
Согласитесь, что все было бы лучшим выбором. Похмелье от других языков. - person James King; 22.12.2013