3

私は、多数のテキストファイルから一意の単語を解析するプロジェクトに取り組んでいます。ファイル処理を停止しましたが、解析手順を改良しようとしています。各ファイルには、ライブシステムで正規表現を使用してキャッチしている特定のフレーズで終わる特定のテキストセグメントがあります。

パーサーは各行をウォークスルーし、3つの基準に対して各単語をチェックする必要があります。

  1. 2文字より長い
  2. 事前定義された辞書セットにありませんdict_file
  3. まだ単語リストにありません

結果は2D配列になり、各行にはファイルごとの一意の単語のリストが表示されます。これは、.writerow(foo)各ファイルが処理された後、メソッドを使用してCSVファイルに書き込まれます。

私の作業コードは以下のとおりですが、遅くて扱いにくいですが、何が欠けていますか?

私の本番システムは、デフォルトのモジュールだけで2.5.1を実行しているため(NLTKは使用できません)、2.7以降にアップグレードすることはできません。

def process(line):
    line_strip = line.strip()
    return line_strip.translate(punct, string.punctuation)

# Directory walking and initialization here
report_set = set()
with open(fullpath, 'r') as report:
    for line in report:
        # Strip out the CR/LF and punctuation from the input line
        line_check = process(line)
        if line_check == "FOOTNOTES":
            break
        for word in line_check.split():
            word_check = word.lower()
            if ((word_check not in report_set) and (word_check not in dict_file) 
                 and (len(word) > 2)):
                report_set.append(word_check)
report_list = list(report_set)

編集:stevehaの推奨事項に基づいてコードを更新しました。

4

2 に答える 2

3

1つの問題は、inaのテストlistが遅いことです。aのテストは非常に高速であるsetため、見た単語を追跡するためにaを保持する必要があります。inset

例:

report_set = set()
for line in report:
    for word in line.split():
        if we_want_to_keep_word(word):
            report_set.add(word)

次に、完了したら:report_list = list(report_set)

setを強制する必要があるときはいつでもlist、できます。ただし、ループしたりinテストを実行したりする必要がある場合は、そのままにしておくことができますset。行うことは合法ですfor x in report_set:

問題になるかもしれないし、問題にならないかもしれない別の問題は、.readlines()メソッドを使用して、ファイルからすべての行を一度に丸呑みしていることです。非常に大きなファイルの場合は、次のように、開いているファイルハンドルオブジェクトをイテレータとして使用することをお勧めします。

with open("filename", "r") as f:
    for line in f:
        ... # process each line here

大きな問題は、このコードがどのように機能するかさえわからないことです。

while 1:
    lines = report.readlines()
    if not lines:
        break

これは永久にループします。最初のステートメントはすべての入力行をで丸呑みし.readlines()、次に再びループし、次の呼び出し.readlines()reportすでに使い果たされているため、への呼び出し.readlines()は空のリストを返します。これは無限ループから抜け出します。しかし、これで今読んだすべての行が失われ、残りのコードは空のlines変数で処理する必要があります。これはどのように機能しますか?

したがって、そのループ全体を取り除きwhile 1、次のループをに変更しますfor line in report:

countまた、変数を保持する必要はありません。いつでも使用len(report_set)して、に含まれる単語の数を調べることができますset

また、aを使用すると、単語がセットsetであるかどうかを実際に確認する必要はありません。inいつでも電話をかけることができreport_set.add(word)、すでにその中にある場合は、set再度追加されることはありません。

また、私のやり方で行う必要はありません、すべての処理を行うジェネレーターを作成するのが好きです。行を削除し、行を翻訳し、空白で分割して、すぐに使用できる単語を生成します。FOOTNOTESまた、大文字でのみ検出されることが重要かどうかわからない場合を除いて、単語を小文字に強制します。

したがって、上記のすべてをまとめると、次のようになります。

def words(file_object):
    for line in file_object:
        line = line.strip().translate(None, string.punctuation)
        for word in line.split():
            yield word

report_set = set()
with open(fullpath, 'r') as report:
    for word in words(report):
        if word == "FOOTNOTES":
            break
        word = word.lower()
        if len(word) > 2 and word not in dict_file:
            report_set.add(word)

print("Words in report_set: %d" % len(report_set))
于 2012-06-20T01:09:01.530 に答える
2

report_listを辞書またはセットに置き換えてみてください。report_listがリストの場合、report_listにないword_checkの動作が遅くなります

于 2012-06-20T01:08:57.380 に答える