1

私は最近、巨大なテキストファイルを操作しています。行を削除する必要がある場合があります。私のやり方は以下のようなものです:

f=open('txt','r').readlines()
list=[]
for line in f:
    if blablablabla:
       list.append(line)

大きなファイルの場合、.readlines()は律速段階ですが、.append()段階はどうですか?追加は、readlineの後に多くの余分な時間を要しますか?もしそうなら、多分私は私が望む行を追加する代わりに、私が望まない行を直接削除する方法を見つけるべきです。

どうも

4

5 に答える 5

5

readlines()後でフィルタリングする場合は、ファイル全体を使用して読み取るのはなぜですか?保持したい行を保存して、それを繰り返すだけです。代わりにリスト内包表記を使用して、これを数行に減らすことができます。

with open('txt', 'r') as f:
    myList = [ line for line in f if blablablabla ]
于 2011-08-23T21:23:11.607 に答える
2

一般的なヒントとして、代わりにこれを実行してください。反復する前に、最初にファイル全体を読み取る必要はありません...

with open('txt') as fd:
    for line in fd:
        if blablabla:
            my_list.append(line)

リストを「リスト」とは呼ばないでください...

于 2011-08-23T21:24:08.587 に答える
1

ジェフの答えのように、代わりにリスト内包表記を使用する必要があります。データの処理方法によっては、代わりにジェネレータ式を使用できる場合があります。

append()に関する質問に答えるには

Pythonリストは事前に割り当てられており、最後に余分なスペースがあります。これは、事前に割り当てられたスペースがなくなるまで、追加が非常に高速であることを意味します。リストが拡張されるたびに、新しいメモリブロックが割り当てられ、すべての参照がそのブロックにコピーされます。リストが大きくなると、事前に割り当てられた余分なスペースのサイズも大きくなります。これは、appendがO(1)で償却されるように行われます。つまり、追加の平均時間は高速で一定です

于 2011-08-23T21:36:09.867 に答える
1

この投稿では、リストが機能する方法と、appendがそれほど高価ではない理由を説明しようとしました。また、行を削除するために使用できる解決策を下部に投稿しました。

Pythonのリストの構造は、ノードネットワークのようなものです。

>>> class ListItem:
        def __init__(self, value, next=None):
            self.value = value
            self.next = next
        def __repr__(self):
            return "Item: %s"%self.value


>>> ListItem("a", ListItem("b", ListItem("c")))
Item: a
>>> mylist = ListItem("a", ListItem("b", ListItem("c")))
>>> mylist.next.next
Item: c

したがって、appendは基本的にこれだけです:

ListItem(mynewvalue, oldlistitem)

Appendにはそれほどオーバーヘッドはありませんがinsert()、一方で、リスト全体を再構築する必要があるため、はるかに時間がかかります。

>>> from timeit import timeit
>>> timeit('a=[]\nfor i in range(100): a.append(i)', number=1000)
0.03651859015577941
>>> timeit('a=[]\nfor i in range(100): a.insert(0, i)', number=1000)
0.047090002177625934
>>> timeit('a=[]\nfor i in range(100): a.append(i)', number=10000)
0.18015429656996673
>>> timeit('a=[]\nfor i in range(100): a.insert(0, i)', number=10000)
0.35550057300308424

ご覧のとおり、挿入ははるかに遅くなります。もし私があなたなら、すぐに書き戻すことで、あなたが必要としない行を削除するでしょう。

with open("large.txt", "r") as fin:
    with open("large.txt", "w") as f:
        for line in fin:
            if myfancyconditionismet:
                # write the line to the file again
                f.write(line + "\n")
            # otherwise it is gone

私の説明と解決策があります。

-Sunjay03

于 2011-08-23T21:39:56.107 に答える
0

たぶん、それをすべてメモリにプルしてから操作したいと思うでしょう。たぶん、一度に1つの回線で操作する方が理にかなっています。あなたの説明からどちらが良いかは明らかではありません。

いずれにせよ、これはあなたが取るアプローチのためのかなり標準的なコードです:

# Pull one line into memory at a time
with open('txt','r') as f:
    lineiter = (line for line in f if blablablabla)
    for line in lineiter:
        # Do stuff

# Read the whole file into memory then work on it
with open('txt','r') as f:
    lineiter = (line for line in f if blablablabla)
    mylines = [line for line in lineiter]

前者のルートを利用する場合は、ジェネレーターを確認することをお勧めします。Dave Beazleyは、 「システムプログラマーのためのジェネレータートリック」と呼ばれるジェネレーターに関するすばらしい記事を掲載しています。強くお勧めします。

于 2011-08-24T01:59:57.580 に答える