2016-03-18 14 views
5

ファイルからデータを取り出すために次の関数を作成しました。それは正常に動作しますが、大きなファイルでは非常に遅くなります。ファイルを複数回反復せずにデータを取り出す

def get_data(file, indexes, data_start, sieve_first = is_float): 
    file_list = list(file) 
    for i in indexes: 
     d_line = i+data_start 
     for line in file_list[d_line:]: 
      if sieve_first(line.strip().split(',')[0]): 
       yield file_list[d_line].strip() 
       d_line += 1 
      else: 
       break 

def is_float(f): 
    try: 
     float(str(f)) 
    except: 
     return False 
    else: 
     return True 

with open('my_data') as f: 
    data = get_data(f, index_list, 3) 

ファイルは(行番号が、明確にするために追加された)のようになります。上記の例を

line 1234567: # <-- INDEX 
line 1234568: # +1 
line 1234569: # +2 
line 1234570:  8, 17.0, 23, 6487.6 
line 1234571:  8, 17.0, 23, 6487.6 
line 1234572:  8, 17.0, 23, 6487.6 
line 1234572: 
line 1234572: 
line 1234572: 

、1234572スルーライン1234570が得られます。

私のファイルが大きいので、自分の機能について嫌いなことがいくつかあります。

  1. まず、ファイル全体をメモリに読み込みます。私はこれを行うので、データを解析するために行の索引付けを使用できます。
  2. 第2に、ファイル内の同じ行が何度も繰り返し処理されるということです。これは、大きなファイルでは非常に高価になります。

私はイテレータを使用してファイルを一度に抜け出そうとしていましたが、それを解読することはできませんでした。助言がありますか?

+0

'list(file) 'の代わりに' for line in file'を実行してください。 –

+0

@ cricket_007ありがとうございます。ただし、 'file'がインデックス作成をサポートしていない場合、残りの関数は動作しません。 –

+0

ファイルが索引付けをサポートしていなかった場合、どのように 'file [d_line:]'をやっていますか? –

答えて

2

ファイルのほんの一部分だけが必要な場合は、itertools.isliceを使用します。この関数は、データを保存するのではなく、必要なデータをメモリに保存します。ここで

は例です:

from itertools import islice 

def yield_specific_lines_from_file(filename, start, stop): 
    with open(filename, 'rb') as ifile: 
     for line in islice(ifile, start, stop): 
      yield line 

lines = list(yield_specific_lines_from_file('test.txt', 10, 20)) 

あなたは、Python 3.3以降を使用する場合は、あなたもyield fromステートメントを使用してこれを簡素化することができます。

from itertools import islice 

def yield_specific_lines_from_file(filename, start, stop): 
    with open(filename, 'rb') as ifile: 
     yield from islice(ifile, start, stop) 

lines = list(yield_specific_lines_from_file('test.txt', 10, 20)) 

これは、あなたがきたラインをキャッシュしません。すでにファイルから読み込まれています。これを行うには、すべての読み取り行をキーとして行番号を含む辞書に格納し、必要に応じてファイルからデータを取り出すことをお勧めします。

+1

は 'islice'のように見えます。まだ複数回繰り返す必要がありますが、この方法でははるかに安価です。ありがとう。 –

1

左のフィールドから少しです。しかし、あなたがファイルを制御できるならば、あなたはsqlite3 dbにデータを移動できます。

また、mmapとlinecacheを見てください。これらの最後の2つは、ランダムアクセスファイルのラッパーです。つまり、ファイルを一度スキャンして索引 - >オフセットルックアップテーブルを作成し、シークを使用して自分自身をロールバックすることができます。

これらのアプローチの中には、読んでいるファイルを何らかの形で管理していると仮定しているものがありますか?

また、頻繁に読み書きするかどうかによって異なります(インデックスを作成することは悪い考えではありません)。

+0

多くのことを読んで書いていることはほとんどありませんが、おそらく今やっています。素晴らしいアイデア - ありがとう! –

関連する問題