Compruebe si existen varias cadenas en otra cadena

378

¿Cómo puedo verificar si alguna de las cadenas de una matriz existe en otra cadena?

Me gusta:

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"

Ese código no funciona, es solo para mostrar lo que quiero lograr.

jahmax
fuente
55
Me sorprende que no haya (todavía) ninguna respuesta en comparación con una expresión regular compilada en términos de rendimiento, especialmente en comparación con el tamaño de la cadena y el número de "agujas" para buscar.
Pat
3
@ Pat no estoy sorprendido. La pregunta no es sobre el rendimiento. Hoy en día, la mayoría de los programadores se preocupan más por lograrlo y por su legibilidad. La pregunta de rendimiento es válida, pero una pregunta diferente.
guettli
13
Usar str como variable es confuso y puede provocar un comportamiento inesperado, ya que es una palabra reservada; ver enlace .
Chico inteligente
regex [abc]también funciona perfectamente bien y será más rápido si hay más de un par de candidatos para evaluar. Pero si las cadenas son arbitrarias y no las conoce de antemano para construir una expresión regular, tendrá que usar el any(x in str for x in a)enfoque.
smci
@CleverGuy Tienes razón, aunque no es una palabra reservada, de lo contrario no podrías asignarla. Es una construcción.
wjandrea

Respuestas:

717

Puedes 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):

De manera similar, para verificar si se encuentran todas las cadenas de la lista, use en alllugar de any.

Mark Byers
fuente
11
any () toma un iterable. No estoy seguro de qué versión de Python está utilizando, pero en 2.6 deberá colocar [] alrededor de su argumento en any (). any ([x en str para x en a]) para que la comprensión devuelva un iterable. Pero tal vez las versiones posteriores de Python ya hacen esto.
emispowder
77
@ Mark Byers: Perdón por el comentario tardío, pero ¿hay alguna forma de imprimir la cadena que se encontró? Cómo harías esto. Gracias.
Shankar Kumar el
3
No estoy seguro de entender, si a es la lista, y str es lo que debe coincidir, ¿cuál es la x? Python newbie ftw. :)
rojo
2
@red: puede leer for x in acomo "para cada elemento de la lista". Dado que aes una lista de cadenas, y xes un elemento de esa lista, xes una cadena (una de 'a', 'b', 'c' en el ejemplo original)
Usuario
66
@emispowder Funciona bien para mí tal como está en Python 2.6.9.
MPlanchard
67

any()es, con mucho, el mejor enfoque si todo lo que quiere es Trueo False, pero si desea saber específicamente qué cadena / cadenas coinciden, puede usar un par de cosas.

Si desea la primera coincidencia (con el Falsevalor predeterminado):

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

Si desea obtener todas las coincidencias (incluidos los duplicados):

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

Si desea obtener todas las coincidencias no duplicadas (sin tener en cuenta el orden):

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

Si desea obtener todas las coincidencias no duplicadas en el orden correcto:

matches = []
for x in a:
    if x in str and x not in matches:
        matches.append(x)
zondo
fuente
agregue también un ejemplo para el último partido
Oleg Kokorin
@OlegKokorin: crea una lista de cadenas coincidentes en el mismo orden en que las encuentra, pero conserva solo la primera si dos son iguales.
zondo
Usar un OrderedDictes probablemente más eficaz que una lista. Vea esta respuesta en "Eliminar duplicados en listas"
wjandrea
44

Debe tener cuidado si las cuerdas entran ao strse alargan. Las soluciones directas toman O (S * (A ^ 2)), donde Ses la longitud de stry A es la suma de las longitudes de todas las cadenas a. Para una solución más rápida, mire el algoritmo Aho-Corasick para la coincidencia de cadenas, que se ejecuta en tiempo lineal O (S + A).

jbernadas
fuente
¿Puede Aho-Corasick también encontrar subcadenas en lugar de prefijos?
RetroCode
1
Algunas bibliotecas de Python Aho-Corasick están aquí y aquí
vorpal
23

Solo para agregar algo de diversidad con regex:

import re

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

o si tu lista es demasiado larga any(re.findall(r'|'.join(a), str, re.IGNORECASE))

Shankar ARUL - jupyterdata.com
fuente
1
Esto funciona para el caso de uso dado de la pregunta. Si busca (o *esto falla, ya que se debe citar la sintaxis de expresiones regulares.
guettli
2
Puede escapar si es necesario con '|'.join(map(re.escape, strings_to_match)). Probablemente re.compile('|'.join(...))también deberías .
Artyer
12

Necesita iterar sobre los 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
fuente
2
Sí, sabía cómo hacerlo, pero en comparación con la respuesta de Marks, ese es un código horrible.
jahmax
11
Solo si entiendes el código de Mark. El problema que tenía es que no estaba examinando los elementos de su matriz. Hay muchas formas concisas y pitónicas para lograr lo que desea que ocultaría la esencia de lo que estaba mal con su código.
Seamus Campbell
10
Puede ser 'código horrible' pero es exactamente lo que hace cualquier () . Además, esto le da la cadena real que coincide, mientras que any () simplemente le dice que hay una coincidencia.
alldayremix 01 de
4

jbernadas ya mencionó el algoritmo Aho-Corasick-Algoritmo para reducir la complejidad.

Aquí hay una forma de usarlo en Python:

  1. Descargue aho_corasick.py desde aquí

  2. Póngalo en el mismo directorio que su archivo Python principal y asígnele un nombre aho_corasick.py

  3. Pruebe el alroritmo con el siguiente código:

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

Tenga en cuenta que la búsqueda distingue entre mayúsculas y minúsculas

Domi W
fuente
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
fuente
1

Depende del contexto supongo que si usted quiere comprobar sola literal como (palabra única a, e, w, etc ..) en es suficiente

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

si desea verificar cualquiera de los caracteres entre la palabra original: utilice

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

si desea toda la entrada que desea en esa palabra_original, utilice todos los simples

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
fuente
¿Cuál sería tu entrada? Puedo reconocer dos cosas: la oración donde estoy buscando algo. La variedad de palabras que estoy buscando. Pero usted describe tres variables y no puedo entender cuál es la tercera.
Mayid
1

Solo un poco más de información sobre cómo obtener todos los elementos de la lista disponibles en String

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

Un enfoque sorprendentemente rápido es 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")

Esto funciona si ano contiene ningún valor de caracteres múltiples (en cuyo caso, use anycomo se menciona anteriormente ). Si es así, es más sencillo para especificar acomo una cadena: a = 'abc'.

Berislav Lopac
fuente
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')

imagen de ejemplo de salida

LeftSpace
fuente
0

Usaría este tipo de función para la velocidad:

def check_string(string, substring_list):
    for substring in substring_list:
        if substring in string:
            return True
    return False
Ivan Mikhailov
fuente
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
fuente