Controlla se esistono più stringhe in un'altra stringa


378

Come posso verificare se una delle stringhe in un array esiste in un'altra stringa?

Piace:

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"

Quel codice non funziona, è solo per mostrare ciò che voglio ottenere.


5
Sono sorpreso che non ci siano (ancora) risposte paragonabili a una regex compilata in termini di perf, soprattutto rispetto alla dimensione della stringa e al numero di "aghi" da cercare.
Pat

3
@Pat Non sono sorpreso. La domanda non riguarda le prestazioni. Oggi la maggior parte dei programmatori si preoccupa di più di farlo e leggibilità. La domanda di prestazione è valida, ma una domanda diversa.
Guettli,

13
L'uso di str come variabile è fonte di confusione e può comportare comportamenti imprevisti in quanto è una parola riservata; vedi link .
Clever Guy,

regex [abc]funziona anche perfettamente e sarà più veloce se ci sono più di un paio di candidati da testare. Ma se le stringhe sono arbitrarie e non le conosci in anticipo per costruire una regex, dovrai usare l' any(x in str for x in a)approccio.
smci

@CleverGuy Hai ragione, anche se non è una parola riservata, altrimenti non potresti assegnarla. È incorporato.
wjandrea,

Risposte:


717

Puoi usare any:

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

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

Allo stesso modo per verificare se tutte le stringhe dell'elenco sono state trovate, utilizzare allinvece di any.


11
any () accetta un iterabile. Non sono sicuro di quale versione di Python stai usando, ma in 2.6 dovrai mettere [] attorno al tuo argomento a any (). qualsiasi ([x in str per x in a]) in modo che la comprensione ritorni un iterabile. Ma forse le versioni successive di Python lo fanno già.
emispowder

7
@Mark Byers: scusate il commento in ritardo, ma c'è un modo per stampare la stringa trovata? Come lo faresti. Grazie.
Shankar Kumar,

3
Non sono sicuro di capire, se a è la lista e str è la cosa con cui confrontarsi, qual è la x? Python newbie ftw. :)
rosso

2
@red: puoi leggere for x in acome "per ogni elemento nell'elenco". Poiché aè un elenco di stringhe, ed xè un elemento di tale elenco, xè una stringa (una di 'a', 'b', 'c' nell'esempio originale)
Utente

6
@emispowder Funziona bene per me così com'è in Python 2.6.9.
MPlanchard,

67

any()è di gran lunga l'approccio migliore se tutto ciò che vuoi è Trueo False, ma se vuoi sapere in modo specifico quale stringa / stringhe corrispondono, puoi usare un paio di cose.

Se si desidera la prima corrispondenza (con Falsecome predefinito):

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

Se vuoi ottenere tutte le partite (inclusi i duplicati):

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

Se si desidera ottenere tutte le corrispondenze non duplicate (ignorando l'ordine):

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

Se vuoi ottenere tutte le partite non duplicate nel giusto ordine:

matches = []
for x in a:
    if x in str and x not in matches:
        matches.append(x)

per favore, aggiungi un esempio anche per l'ultima partita
Oleg Kokorin,

@OlegKokorin: crea un elenco di stringhe corrispondenti nello stesso ordine in cui le trova, ma mantiene solo la prima se due sono uguali.
zondo,

L'uso di an OrderedDictè probabilmente più performante di un elenco. Vedi questa risposta su "Rimozione dei duplicati negli elenchi"
wjandrea

44

Dovresti stare attento se le stringhe si allungano ao strsi allungano. Le soluzioni semplici prendono O (S * (A ^ 2)), dove Sè la lunghezza di stre A è la somma delle lunghezze di tutte le stringhe a. Per una soluzione più veloce, guarda l' algoritmo Aho-Corasick per la corrispondenza delle stringhe, che gira in tempo lineare O (S + A).


Aho-Corasick può trovare anche sottostringhe anziché prefissi?
RetroCode

1
Alcune librerie di Aho-Corasick in pitone sono qui e qui
vorpal,

23

Solo per aggiungere un po 'di diversità 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 se la tua lista è troppo lunga - any(re.findall(r'|'.join(a), str, re.IGNORECASE))


1
Questo funziona per il caso d'uso della domanda. Se la ricerca (o *questo non riesce, poiché è necessario eseguire la quotazione per la sintassi della regex.
Guettli,

2
Puoi scappare se necessario con '|'.join(map(re.escape, strings_to_match)). Probabilmente re.compile('|'.join(...))anche tu .
Artyer,

12

Devi iterare sugli elementi di 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"

2
Sì, sapevo come farlo, ma rispetto alla risposta di Marks, è un codice orribile.
jahmax,

11
Solo se capisci il codice di Mark. Il problema che stavi riscontrando è che non stavi esaminando gli elementi del tuo array. Esistono molti modi concisi e concreti per realizzare ciò che vuoi che nasconderebbe l'essenza di ciò che era sbagliato nel tuo codice.
Seamus Campbell,

10
Potrebbe essere un 'codice orribile' ma è esattamente ciò che fa qualsiasi () . Inoltre, questo ti dà la stringa effettiva che corrisponde, mentre any () ti dice solo che c'è una corrispondenza.
alldayremix

4

jbernadas ha già menzionato l' algoritmo Aho-Corasick per ridurre la complessità.

Ecco un modo per usarlo in Python:

  1. Scarica aho_corasick.py da qui

  2. Inseriscilo nella stessa directory del tuo file Python principale e chiamalo aho_corasick.py

  3. Prova l'alroritmo con il seguente codice:

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

Si noti che la ricerca fa distinzione tra maiuscole e minuscole


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"

1

Dipende dal contesto Supponiamo che se si desidera controllare singolo letterale come (qualsiasi parola a, e, w, .. ecc) in è sufficiente

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

se vuoi controllare uno qualsiasi dei caratteri tra la original_word: usa

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

se vuoi tutto l'input che vuoi in quella original_word, usa tutto semplice

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")

Quale sarebbe il tuo input? Riesco a riconoscere due cose: la frase in cui sto cercando qualcosa. La gamma di parole che sto cercando. Ma descrivi tre variabili e non riesco a capire quale sia la terza.
mayid

1

Altre informazioni su come ottenere tutti gli elementi dell'elenco disponibili in String

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

1

Un approccio sorprendentemente veloce è usare 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")

Funziona se anon contiene valori con più caratteri (nel qual caso utilizzare anycome elencato sopra ). Se è così, è più semplice per specificare acome stringa: a = 'abc'.


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')

immagine di esempio di output


0

Vorrei usare questo tipo di funzione per la velocità:

def check_string(string, substring_list):
    for substring in substring_list:
        if substring in string:
            return True
    return False

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)));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.