Verifique se existem várias strings em outra string

378

Como posso verificar se alguma das strings de uma matriz existe em outra string?

Gostar:

a = ['a', 'b', 'c']
str = "a123"
if a in str:
  print "some of the strings found in str"
else:
  print "no strings found in str"

Esse código não funciona, é apenas para mostrar o que eu quero alcançar.

jahmax
fonte
5
Estou surpreso por ainda não haver respostas comparadas a um regex compilado em termos de desempenho, especialmente se comparado ao tamanho da sequência e ao número de "agulhas" a serem pesquisadas.
Pat
3
@ Pat Não estou surpreso. A questão não é sobre desempenho. Hoje, a maioria dos programadores se preocupa mais com o desempenho e a legibilidade. A questão do desempenho é válida, mas uma questão diferente.
guettli
13
Usar str como uma variável é confuso e pode resultar em comportamento inesperado, pois é uma palavra reservada; veja o link .
Cara Inteligente
O regex [abc]também funciona perfeitamente bem e será mais rápido se houver mais de dois candidatos para testar. Mas se as seqüências de caracteres são arbitrárias e você não as conhece antecipadamente para construir uma regex, terá que usar a any(x in str for x in a)abordagem.
smci 8/01
@CleverGuy Você está certo, embora não seja uma palavra reservada, caso contrário você não poderá atribuir a ela. É um builtin.
wjandrea

Respostas:

717

Você pode usar any:

a_string = "A string is more than its parts!"
matches = ["more", "wholesome", "milk"]

if any(x in a_string for x in matches):

Da mesma forma, para verificar se todas as strings da lista foram encontradas, use em allvez de any.

Mark Byers
fonte
11
any () leva um iterável. Não tenho certeza de qual versão do Python você está usando, mas no 2.6 você precisará colocar [] em torno do seu argumento para any (). any ([x em str para x em a]) para que a compreensão retorne um iterável. Mas talvez versões posteriores do Python já façam isso.
emispowder
7
@ Mark Byers: Desculpe pelo comentário tardio, mas existe uma maneira de imprimir a string que foi encontrada? Como você faria isso. Obrigado.
precisa saber é o seguinte
3
Não tenho certeza se entendi, se a é a lista e str é a coisa com a qual comparar, qual é o x? Iniciante em Python ftw. :)
vermelho
2
@red: você pode ler for x in acomo "para cada elemento da lista". Desde aé uma lista de strings, e xé um elemento dessa lista, xé uma string (um dos 'a', 'b', 'c' no exemplo original)
Utilizador
6
@emispowder Funciona bem para mim como está no Python 2.6.9.
MPlanchard
67

any()é, de longe, a melhor abordagem, se tudo o que você quer é Trueou False, mas se você deseja saber especificamente quais strings / strings correspondem, você pode usar algumas coisas.

Se você deseja a primeira correspondência (com o Falsepadrão):

match = next((x for x in a if x in str), False)

Se você deseja obter todas as correspondências (incluindo duplicatas):

matches = [x for x in a if x in str]

Se você deseja obter todas as correspondências não duplicadas (independentemente da ordem):

matches = {x for x in a if x in str}

Se você deseja obter todas as correspondências não duplicadas na ordem correta:

matches = []
for x in a:
    if x in str and x not in matches:
        matches.append(x)
zondo
fonte
por favor, adicione também exemplo para a última partida
Oleg Kokorin 02/04
@OlegKokorin: Cria uma lista de strings correspondentes na mesma ordem em que as encontra, mas mantém apenas a primeira se duas forem iguais.
Zart
Usar um OrderedDictprovavelmente é mais eficiente que uma lista. Veja esta resposta em "Removendo duplicatas em listas"
wjandrea
44

Você deve ter cuidado se as cordas entrarem aou ficarem strmais longas. As soluções simples levam O (S * (A ^ 2)), onde Sé o comprimento de stre A é a soma dos comprimentos de todas as seqüências de caracteres em a. Para uma solução mais rápida, observe o algoritmo Aho-Corasick para correspondência de cadeias, que é executado no tempo linear O (S + A).

jbernadas
fonte
Aho-Corasick também pode encontrar substrings em vez de prefixos?
RetroCode 26/09/16
11
Alguns python Aho-Corasick bibliotecas estão aqui e aqui
vorpal
23

Apenas para adicionar um pouco de diversidade com regex:

import re

if any(re.findall(r'a|b|c', str, re.IGNORECASE)):
    print 'possible matches thanks to regex'
else:
    print 'no matches'

ou se sua lista for muito longa - any(re.findall(r'|'.join(a), str, re.IGNORECASE))

Shankar ARUL - jupyterdata.com
fonte
11
Isso funciona para o caso de uso especificado da pergunta. Se você procurar (ou *isso falhar, é necessário fazer a citação para a sintaxe regex.
guettli
2
Você pode escapar se necessário com '|'.join(map(re.escape, strings_to_match)). Você provavelmente deveria re.compile('|'.join(...))também.
Artyer
12

Você precisa iterar nos elementos de a.

a = ['a', 'b', 'c']
str = "a123"
found_a_string = False
for item in a:    
    if item in str:
        found_a_string = True

if found_a_string:
    print "found a match"
else:
    print "no match found"
Seamus Campbell
fonte
2
Sim, eu sabia como fazer isso, mas comparado à resposta do Marks, esse código é horrível.
Jahmax # 02
10
Somente se você entender o código de Mark. O problema que você estava tendo é que não estava examinando os elementos da sua matriz. Existem muitas maneiras concisas e pitônicas de realizar o que você deseja que ocultem a essência do que estava errado com seu código.
Seamus Campbell
9
Pode ser um 'código horrível', mas é exatamente o que qualquer () faz . Além disso, isso fornece a string real que correspondeu, enquanto any () apenas informa que há uma correspondência.
Aldayremix #
4

jbernadas já mencionou o algoritmo Aho-Corasick para reduzir a complexidade.

Aqui está uma maneira de usá-lo em Python:

  1. Faça o download do aho_corasick.py aqui

  2. Coloque-o no mesmo diretório do seu arquivo Python principal e nomeie-o aho_corasick.py

  3. Tente o alrorithm com o seguinte código:

    from aho_corasick import aho_corasick #(string, keywords)
    
    print(aho_corasick(string, ["keyword1", "keyword2"]))

Observe que a pesquisa diferencia maiúsculas de minúsculas

Domi W
fonte
3
a = ['a', 'b', 'c']
str =  "a123"

a_match = [True for match in a if match in str]

if True in a_match:
  print "some of the strings found in str"
else:
  print "no strings found in str"
mluebke
fonte
1

Depende do contexto suponho que se você quiser verificar literal única como (qualquer única palavra a, e, w, .. etc) em é suficiente

original_word ="hackerearcth"
for 'h' in original_word:
      print("YES")

se você quiser verificar algum dos caracteres entre a palavra_ original: faça uso de

if any(your_required in yourinput for your_required in original_word ):

se você quiser toda a entrada que desejar nessa palavra_ original, use todas as

original_word = ['h', 'a', 'c', 'k', 'e', 'r', 'e', 'a', 'r', 't', 'h']
yourinput = str(input()).lower()
if all(requested_word in yourinput for requested_word in original_word):
    print("yes")
Trinadh Koya
fonte
Qual seria a sua entrada? Eu posso reconhecer duas coisas: a frase em que estou procurando algo. A variedade de palavras que estou procurando. Mas você descreve três variáveis ​​e eu não consigo entender qual é a terceira.
1919 Mayid
1

Apenas mais algumas informações sobre como obter todos os elementos da lista disponíveis em String

a = ['a', 'b', 'c']
str = "a123" 
list(filter(lambda x:  x in str, a))
Nilesh Birari
fonte
1

Uma abordagem surpreendentemente rápida é usar set:

a = ['a', 'b', 'c']
str = "a123"
if set(a) & set(str):
    print("some of the strings found in str")
else:
    print("no strings found in str")

Isso funciona se anão contiver nenhum valor de vários caracteres (nesse caso, use anycomo listado acima ). Se assim for, é mais simples para especificar acomo uma string: a = 'abc'.

Berislav Lopac
fonte
0
flog = open('test.txt', 'r')
flogLines = flog.readlines()
strlist = ['SUCCESS', 'Done','SUCCESSFUL']
res = False
for line in flogLines:
     for fstr in strlist:
         if line.find(fstr) != -1:
            print('found') 
            res = True


if res:
    print('res true')
else: 
    print('res false')

imagem de exemplo de saída

LeftSpace
fonte
0

Eu usaria esse tipo de função para velocidade:

def check_string(string, substring_list):
    for substring in substring_list:
        if substring in string:
            return True
    return False
Ivan Mikhailov
fonte
0
data = "firstName and favoriteFood"
mandatory_fields = ['firstName', 'lastName', 'age']


# for each
for field in mandatory_fields:
    if field not in data:
        print("Error, missing req field {0}".format(field));

# still fine, multiple if statements
if ('firstName' not in data or 
    'lastName' not in data or
    'age' not in data):
    print("Error, missing a req field");

# not very readable, list comprehension
missing_fields = [x for x in mandatory_fields if x not in data]
if (len(missing_fields)>0):
    print("Error, missing fields {0}".format(", ".join(missing_fields)));
Robert I
fonte