2010-10-18 11 views

risposta

11

Se non si desidera avere 2 problemi:

for word in file('myfile.txt').read().split(): 
    if 'x' in word and 'z' in word: 
     print word 
+1

Grazie a Dio hai fornito una risposta che * non * usa espressioni regolari. – gotgenes

+0

+1: mi piace molto. L'unico problema che riesco a vedere è che otterrai anche la punteggiatura che circonda le tue parole, non solo le parole stesse. –

+0

Vero, sto usando la definizione Python di "parole", che potrebbe essere irragionevole qui. – geoffspear

0

Sembra un lavoro per Regular Expressions. Leggilo e provalo. Se riscontri problemi, aggiorna la tua domanda e possiamo aiutarti con le specifiche.

8

Supponendo di avere l'intero file come una stringa di grandi dimensioni in memoria, e che la definizione di una parola è "una sequenza contigua di lettere", allora si potrebbe fare qualcosa di simile:

import re 
for word in re.findall(r"\w+", mystring): 
    if 'x' in word and 'z' in word: 
     print word 
+0

Mi piace questa risposta. È la soluzione più pulita. Se le prestazioni diventano un problema, dedicalo alla mia soluzione e scegli il vincitore. –

3
>>> import re 
>>> pattern = re.compile('\b(\w*z\w*x\w*|\w*x\w*z\w*)\b') 
>>> document = '''Here is some data that needs 
... to be searched for words that contain both z 
... and x. Blah xz zx blah jal akle asdke asdxskz 
... zlkxlk blah bleh foo bar''' 
>>> print pattern.findall(document) 
['xz', 'zx', 'asdxskz', 'zlkxlk'] 
+0

Posso confermare che funziona ed è migliore della mia risposta. Cancellerò il mio a favore di questo. – Ishpeck

0
>>> import re 
>>> print re.findall('(\w*x\w*z\w*|\w*z\w*x\w*)', 'axbzc azb axb abc axzb') 
['axbzc', 'axzb'] 
1

io non conosco le prestazioni di questo generatore, ma per me t il suo è il modo:

from __future__ import print_function 
import string 

bookfile = '11.txt' # Alice in Wonderland 
hunted = 'az' # in your case xz but there is none of those in this book 

with open(bookfile) as thebook: 
    # read text of book and split from white space 
    print('\n'.join(set(word.lower().strip(string.punctuation) 
        for word in thebook.read().split() 
        if all(c in word.lower() for c in hunted)))) 
""" Output: 
zealand 
crazy 
grazed 
lizard's 
organized 
lazy 
zigzag 
lizard 
lazily 
gazing 
"" 

"

3

Voglio solo far notare come pesante consegnato alcune di queste espressioni regolari può essere, rispetto al semplice string methods-based solution provided by Wooble.

Facciamo un po 'di tempo, vero?

#!/usr/bin/env python 
# -*- coding: UTF-8 -*- 

import timeit 
import re 
import sys 

WORD_RE_COMPILED = re.compile(r'\w+') 
Z_RE_COMPILED = re.compile(r'(\b\w*z\w*\b)') 
XZ_RE_COMPILED = re.compile(r'\b(\w*z\w*x\w*|\w*x\w*z\w*)\b') 

########################## 
# Tim Pietzcker's solution 
# https://stackoverflow.com/questions/3962846/how-to-display-all-words-that-contain-these-characters/3962876#3962876 
# 
def xz_re_word_find(text): 
    for word in re.findall(r'\w+', text): 
     if 'x' in word and 'z' in word: 
      print word 


# Tim's solution, compiled 
def xz_re_word_compiled_find(text): 
    pattern = re.compile(r'\w+') 
    for word in pattern.findall(text): 
     if 'x' in word and 'z' in word: 
      print word 


# Tim's solution, with the RE pre-compiled so compilation doesn't get 
# included in the search time 
def xz_re_word_precompiled_find(text): 
    for word in WORD_RE_COMPILED.findall(text): 
     if 'x' in word and 'z' in word: 
      print word 


################################ 
# Steven Rumbalski's solution #1 
# (provided in the comment) 
# https://stackoverflow.com/questions/3962846/how-to-display-all-words-that-contain-these-characters/3963285#3963285 
def xz_re_z_find(text): 
    for word in re.findall(r'(\b\w*z\w*\b)', text): 
     if 'x' in word: 
      print word 


# Steven's solution #1 compiled 
def xz_re_z_compiled_find(text): 
    pattern = re.compile(r'(\b\w*z\w*\b)') 
    for word in pattern.findall(text): 
     if 'x' in word: 
      print word 


# Steven's solution #1 with the RE pre-compiled 
def xz_re_z_precompiled_find(text): 
    for word in Z_RE_COMPILED.findall(text): 
     if 'x' in word: 
      print word 


################################ 
# Steven Rumbalski's solution #2 
# https://stackoverflow.com/questions/3962846/how-to-display-all-words-that-contain-these-characters/3962934#3962934 
def xz_re_xz_find(text): 
    for word in re.findall(r'\b(\w*z\w*x\w*|\w*x\w*z\w*)\b', text): 
     print word 


# Steven's solution #2 compiled 
def xz_re_xz_compiled_find(text): 
    pattern = re.compile(r'\b(\w*z\w*x\w*|\w*x\w*z\w*)\b') 
    for word in pattern.findall(text): 
     print word 


# Steven's solution #2 pre-compiled 
def xz_re_xz_precompiled_find(text): 
    for word in XZ_RE_COMPILED.findall(text): 
     print word 


################################# 
# Wooble's simple string solution 
def xz_str_find(text): 
    for word in text.split(): 
     if 'x' in word and 'z' in word: 
      print word 


functions = [ 
     'xz_re_word_find', 
     'xz_re_word_compiled_find', 
     'xz_re_word_precompiled_find', 
     'xz_re_z_find', 
     'xz_re_z_compiled_find', 
     'xz_re_z_precompiled_find', 
     'xz_re_xz_find', 
     'xz_re_xz_compiled_find', 
     'xz_re_xz_precompiled_find', 
     'xz_str_find' 
] 

import_stuff = functions + [ 
     'text', 
     'WORD_RE_COMPILED', 
     'Z_RE_COMPILED', 
     'XZ_RE_COMPILED' 
] 


if __name__ == '__main__': 

    text = open(sys.argv[1]).read() 
    timings = {} 
    setup = 'from __main__ import ' + ','.join(import_stuff) 
    for func in functions: 
     statement = func + '(text)' 
     timer = timeit.Timer(statement, setup) 
     min_time = min(timer.repeat(3, 10)) 
     timings[func] = min_time 


    for func in functions: 
     print func + ":", timings[func], "seconds" 

esecuzione di questo script su un plaintext copy of Moby Dick ottenuto da Project Gutenberg, su Python 2.6, ottengo i seguenti orari:

xz_re_word_find: 1.21829485893 seconds 
xz_re_word_compiled_find: 1.42398715019 seconds 
xz_re_word_precompiled_find: 1.40110301971 seconds 
xz_re_z_find: 0.680151939392 seconds 
xz_re_z_compiled_find: 0.673038005829 seconds 
xz_re_z_precompiled_find: 0.673489093781 seconds 
xz_re_xz_find: 1.11700701714 seconds 
xz_re_xz_compiled_find: 1.12773990631 seconds 
xz_re_xz_precompiled_find: 1.13285303116 seconds 
xz_str_find: 0.590088844299 seconds 

In Python 3.1 (dopo aver usato 2to3 per fissare le dichiarazioni di stampa), ottengo le seguenti tempistiche:

xz_re_word_find: 2.36110496521 seconds 
xz_re_word_compiled_find: 2.34727501869 seconds 
xz_re_word_precompiled_find: 2.32607793808 seconds 
xz_re_z_find: 1.32204890251 seconds 
xz_re_z_compiled_find: 1.34104800224 seconds 
xz_re_z_precompiled_find: 1.34424304962 seconds 
xz_re_xz_find: 2.33851099014 seconds 
xz_re_xz_compiled_find: 2.29653286934 seconds 
xz_re_xz_precompiled_find: 2.32416701317 seconds 
xz_str_find: 0.656699895859 seconds 

possiamo vedere che le funzioni basate su espressioni regolari tendono a prendere il doppio del tempo per l'esecuzione come la strin g funzione basata su metodi in Python 2.6 e oltre 3 volte più lunga in Python 3. La differenza di tempo è banale per l'analisi una tantum (a nessuno mancheranno quei millisecondi), ma per i casi in cui la funzione deve essere chiamata più volte, l'approccio basato su metodi stringa è sia più semplice che più veloce.

+0

Anch'io preferisco i metodi di stringa. Ma ecco un nitpick.Ho cambiato la definizione di zx_re_find (testo) ed è 4x più veloce del metodo di stringa pura: def zx_re_find (testo): pat = re.compile ('(\ b \ w * z \ w * \ b)') per word in pat.findall (testo): se 'x' in parola: parola di stampa –

+0

@Steven Ho aggiornato la mia risposta per includere includere sia la soluzione suggerita nel commento, sia la soluzione fornita come risposta, e ha fatto non ottenere prestazioni 4X con qualsiasi espressione regolare rispetto al metodo stringa. Per me, le soluzioni RE continuano a rimanere indietro. Che testo hai usato per testare la tua performance? – gotgenes

+0

@gotgenes Ho usato la stessa copia in chiaro di Moby Dick. Ho usato python 2.7 su Windows XP su (hmm ... ho dimenticato il chip nel mio portatile da lavoro). Ricordo le prime 3 cifre dei tempi 0.311 per la stringa e 0.088 per la regex (non proprio 4x, ma chiusa). Io sostengo che se i requisiti fossero più complicati, la regex guadagnerebbe in semplicità e prestazioni. –

Problemi correlati