1

データエントリの最大1GBのテキストファイルと、それらをフィルタリングするために使用したい名前の別のリストがあります。各エントリのすべての名前を実行すると、非常に遅くなります。Pythonでこれを行う最も効率的な方法は何ですか?名前がエントリに埋め込まれている場合、ハッシュテーブルを使用することはできますか?名前の部分が一貫して配置されているという事実を利用できますか?

サンプルファイル:

エントリファイル-名前が表示されるまで、エントリの各部分はタブで区切られます

246   lalala   name="Jack";surname="Smith"
1357   dedada   name="Mary";surname="White"
123456  lala   name="Dan";surname="Brown"
555555   lalala   name="Jack";surname="Joe"

名前ファイル-それぞれ改行

Jack
Dan
Ryan

必要な出力-namesファイルに名前が含まれるエントリのみ

246   lalala   name="Jack";surname="Smith"
123456  lala   name="Dan";surname="Brown"
555555   lalala   name="Jack";surname="Joe"
4

4 に答える 4

6

データ構造を使用しsetて名前を保存できます — これは効率的な検索を提供しますが、名前リストが非常に大きい場合、メモリの問題が発生する可能性があります。

一般的な考え方は、すべての名前を反復処理して に追加しset、データ ファイルの各行の各名前が に含まれているかどうかを確認することですset。エントリの形式は変わらないため、単純な正規表現で名前を抽出できるはずです。

名前のサイズで問題が発生した場合は、名前ファイルからnset行を読み取り、並べ替えが必要でない限り、名前のセットごとにプロセスを繰り返すことができます。

于 2012-06-21T05:33:37.817 に答える
2

私の最初の本能は、名前をキーとして持つ辞書を作成することでした。辞書内のキーのハッシュを使用して名前を検索するのが最も効率的であると想定しました。

答えが与えられたので、@ rfwによって、名前のaを使用して、以下のようにコードを編集し、名前のaと。setを使用して2つのメソッドに対してテストしました。dictset

4,000万を超えるレコードと5400を超える名前のダミーデータセットを作成しました。このデータセットを使用すると、setメソッドは一貫して私のマシンで優位に立っていました。

import re
from collections import Counter
import time

# names file downloaded from http://www.tucows.com/preview/520007
# the set contains over 5400 names
f = open('./names.txt', 'r')
names = [ name.rstrip() for name in f.read().split(',') ]
name_set = set(names) # set of unique names
names_dict = Counter(names) # Counter ~= dict of names with counts

# Expect: 246   lalala   name="Jack";surname="Smith"
pattern = re.compile(r'.*\sname="([^"]*)"')

def select_rows_set():
    f = open('./data.txt', 'r')
    out_f = open('./data_out_set.txt', 'a')
    for record in f.readlines():
        name = pattern.match(record).groups()[0]
        if name in name_set:
            out_f.write(record)
    out_f.close()
    f.close()

def select_rows_dict():
    f = open('./data.txt', 'r')
    out_f = open('./data_out_dict.txt', 'a')
    for record in f.readlines():
        name = pattern.match(record).groups()[0]
        if name in names_dict:
            out_f.write(record)
    out_f.close()
    f.close()

if __name__ == '__main__':
    # One round to time the use of name_set
    t0 = time.time()
    select_rows_set()
    t1 = time.time()
    time_for_set = t1-t0
    print 'Total set: ', time_for_set

    # One round to time the use of names_dict
    t0 = time.time()
    select_rows_dict()
    t1 = time.time()
    time_for_dict = t1-t0
    print 'Total dict: ', time_for_dict

Counter本質的に辞書であり、データセットからの構築が容易なaは、アクセス時間にオーバーヘッドを追加しないと想定しました。私が何かを逃しているならば、訂正されてうれしいです。

于 2012-06-21T06:05:05.350 に答える
1

独自の「名前による検索」機能を備えたカスタム データ構造を作成できます。それはある種の辞書のリストになります。これは、辞書のキーとなる「名前」や「姓」など、各行にある重複情報を削除するため、テキスト ファイルのサイズよりも少ないメモリで済みます。少しSQLを知っている場合(ここではほとんど必要ありません)、Pythonを使用して大きなファイルをフィルタリングし、別のコンテンツを使用します

于 2012-06-21T05:48:16.537 に答える
1

あなたのデータは明確にテーブルとして構造化されているため、これが適用される可能性があります。 表形式のデータをメモリに保持するためのデータ構造?

于 2012-06-21T05:43:26.210 に答える