2010-10-18 38 views
6

Tôi có một tệp văn bản và tôi muốn hiển thị tất cả các từ chứa cả ký tự z và x.Làm cách nào để hiển thị tất cả các từ chứa các ký tự này?

Tôi có thể làm như thế nào?

+2

Vấn đề chính xác ở đâu? Bạn đã thử những gì cho đến nay? –

+0

Tôi không biết cách phân tích cú pháp tệp văn bản :) – xRobot

+0

Cụm từ thông dụng là vua khi nói đến phân tích văn bản. Nhìn vào giải pháp của Ishpeck. – Squirrelsama

Trả lời

11

Nếu bạn không muốn có 2 vấn đề:

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

Cảm ơn lòng tốt bạn đã cung cấp câu trả lời rằng * không * sử dụng cụm từ thông dụng. – gotgenes

+0

+1: Tôi rất thích điều này. Vấn đề duy nhất tôi có thể thấy là bạn sẽ nhận được bất kỳ dấu chấm câu nào xung quanh các từ của bạn nữa, không chỉ là các từ của chúng. –

+0

Đúng, tôi đang sử dụng định nghĩa "từ" của python, điều này có thể không hợp lý ở đây. – geoffspear

0

Có vẻ như một công việc cho Regular Expressions. Đọc và thử nó. Nếu bạn gặp sự cố, hãy cập nhật câu hỏi của bạn và chúng tôi có thể giúp bạn với các chi tiết cụ thể.

8

Giả sử bạn có toàn bộ tập tin là một trong chuỗi lớn trong bộ nhớ, và rằng định nghĩa của một từ là "một chuỗi liền kề của các chữ cái", sau đó bạn có thể làm một cái gì đó như thế này:

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

Tôi thích câu trả lời này. Đó là giải pháp sạch nhất. Nếu hiệu suất trở thành một vấn đề, thời gian nó chống lại giải pháp của tôi và chọn người chiến thắng. –

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

Tôi có thể xác nhận tác phẩm này và tốt hơn câu trả lời của tôi. Tôi sẽ xóa tôi để ủng hộ điều này. – 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

tôi không biết hiệu suất của máy phát điện này, nhưng đối với tôi t mình là cách:

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

Tôi chỉ muốn chỉ ra cách nặng tay một số các biểu thức thông thường có thể được, so với đơn giản string methods-based solution provided by Wooble.

Hãy làm một số thời gian, phải không?

#!/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" 

Chạy kịch bản này trên một plaintext copy of Moby Dick thu được từ Project Gutenberg, trên Python 2.6, tôi nhận được timings sau:

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 

Trong Python 3.1 (sau khi sử dụng 2to3 để sửa chữa các báo cáo in), tôi nhận được các thời gian sau:

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 

Chúng tôi có thể thấy rằng các hàm dựa trên biểu thức chính quy có xu hướng mất gấp đôi thời gian để chạy dưới dạng strin Hàm phương thức g trong Python 2.6 và dài hơn 3 lần trong Python 3. Sự chênh lệch thời gian là không quan trọng đối với phân tích cú pháp một lần (không ai bỏ lỡ các mili giây đó), nhưng trong trường hợp hàm phải được gọi nhiều lần, phương pháp dựa trên phương pháp chuỗi đơn giản hơn và nhanh hơn.

+0

Tôi cũng thích các phương thức chuỗi. Nhưng, đây là một nitpick.Tôi đã thay đổi định nghĩa của zx_re_find (văn bản) và nhanh hơn 4x so với phương pháp chuỗi thuần túy: def zx_re_find (văn bản): pat = re.compile ('(\ b \ w * z \ w * \ b)') cho từ trong pat.findall (văn bản): nếu 'x' bằng chữ: từ in –

+0

@Steven Tôi đã cập nhật câu trả lời của tôi bao gồm cả giải pháp được đề xuất trong nhận xét và giải pháp bạn cung cấp làm câu trả lời và không đạt được hiệu suất 4X bằng bất kỳ biểu thức chính quy nào so với phương thức chuỗi. Đối với tôi, các giải pháp RE vẫn còn ở phía sau. Bạn đã sử dụng văn bản nào để kiểm tra hiệu suất của mình? – gotgenes

+0

@gotgenes Tôi đã sử dụng cùng một bản sao thuần túy của Moby Dick. Tôi đã sử dụng python 2.7 trên Windows XP (hmm .. quên chip trong laptop của mình). Tôi nhớ lại 3 chữ số đầu tiên của thời gian 0.311 cho chuỗi và 0.088 cho regex (không thực sự 4x, nhưng đóng). Tôi duy trì rằng nếu các yêu cầu phức tạp hơn, regex sẽ đạt được sự đơn giản và hiệu quả. –

Các vấn đề liên quan