1

Pythonで1つのファイルからすべての偶数行を新しいファイルにコピーする方法は?

偶数は、あるファイルから別のファイルにコピーされたかなりの数の行を非常に選択したい場合の単なる例ですが、例としては良いはずです。

私はこれを使用しますが、非常に非効率的です (約 5 分かかります)。

# foo.txt holds 200,000 lines with 300 values
list = [0, 2, 4, 6, 8, 10..... 199996, 199998]
newfile = open(savefile, "w")
with open("foo.txt", "r") as file:
    for i, line in enumerate(file):
        if i in list:
            newfile.write(line)
newfile.close()

なぜこれが遅いのか説明があればありがたいです.1行ずつ読むのは速く(約15秒)、マニュアルでもアドバイスされています。

編集:申し訳ありません。特定の奇数/偶数の例を探しているわけではありません。これは、20 万個の値のうち約 10 万個を簡単な順序で処理する方法の効果のためだけです。奇数/偶数を処理するより効率的な方法を見つける以外に、ここでの I/O 問題に対する一般的な解決策はありませんか? 取り上げてしまったことを改めてお詫び申し上げます。

4

4 に答える 4

1

その巨大なlist. 最初のファイルを 1 行ずつ読み込んで、1 行おきにスキップします。トグルフラグを使用してこれを行うか、行番号が2で割り切れるかどうかを確認するだけです(私の意見では、より明確です)。

for i, line in enumerate(file):
    if i % 2 == 0:
        newfile.write(line)

あなたの編集に応じてEDIT:あなたの質問は「ファイルから任意の行をコピーする方法は?」です。それは、これらの任意の行がどのように定義されているかに大きく依存します。その答えは、「必要な」行番号のリストを使用しないことです。そのリストの検索には時間がかかり、すべての行で検索する必要があるためです。

基本的に、ファイルからランダムな行を選択できるようにすることが目標である場合は、現在の設定に似たものを使用できますが、検索を高速化するset代わりにを使用します。list一般的なケースの概念実証ソリューションは次のようになります。

import random

# Pick 5000 random lines
wanted_lines = set(random.sample(range(200000), 5000)) # Use a set!
for i, line in enumerate(file):
    if i in wanted_lines: # average-case O(1)
        newfile.write(str(line)+'\n')
于 2013-06-05T14:56:49.243 に答える
1

あなたlistは事前定義されており、たとえばN行ごとにではなく、可能な行インデックスの任意のシーケンスを含めることができると想定しています。

最初に考えられるボトルネックは、O(n) リスト検索 ( i in list) を 200000 回実行していることです。リストを辞書に変換すると、すでに役立つはずです。

listd = dict.fromkeys(list)
.
.
   # this is O(1) instead of O(n)
   if i in listd:

または、ソートされていることがわかっている場合list、またはソートできる場合は、単に次の行のインデックスを追跡します。

list = [0, 2, 4, 6, 8, 10..... 199996, 199998]
nextidx = 0
newfile = open(savefile, "w")
with open("foo.txt", "r") as file:
    for i, line in enumerate(file):
        if i == list[nextidx]:
            newfile.write(line)
            nextidx += 1
newfile.close()
于 2013-06-05T15:03:18.737 に答える
0

このようなもの?

flag = False
with open("test_async_db_access.py", "r") as file:
    for line in file:
        if flag:
            print line
        flag = not flag

これにより、大きなリストを使用する必要がなくなります

編集: 必要な行の任意のリストの場合は、DSM の回答のようにマップ {} を使用します。これにより、O(n) ではなく O(1) 時間で「in」が実行されます。

于 2013-06-05T14:57:04.520 に答える