0

次のテキストファイルがあります。

This is my text file
NUM,123
FRUIT
DRINK
FOOD,BACON
CAR
NUM,456
FRUIT
DRINK
FOOD,BURGER
CAR
NUM,789
FRUIT
DRINK
FOOD,SAUSAGE
CAR
NUM,012
FRUIT
DRINK
FOOD,MEATBALL
CAR

そして、「欲しい」と呼ばれる次のリストがあります。

['123', '789']

私がやろうとしているのは、NUM の後の数字が「希望」と呼ばれるリストにない場合、その行とその下の 4 行が削除されることです。したがって、出力ファイルは次のようになります。

This is my text file
NUM,123
FRUIT
DRINK
FOOD,BACON
CAR
NUM,789
FRUIT
DRINK
FOOD,SAUSAGE
CAR

これまでの私のコードは次のとおりです。

infile = open("inputfile.txt",'r')
data = infile.readlines()

for beginning_line, ube_line in enumerate(data):
    UNIT = data[beginning_line].split(',')[1]
    if UNIT not in wanted:
        del data_list[beginning_line:beginning_line+4]
4

6 に答える 6

4

リストをループしている間は、リストを変更しないでください。

あなたが試すことができるのは、必要に応じてファイルオブジェクトのイテレータを進めることです:

wanted = set(['123', '789'])

with open("inputfile.txt",'r') as infile, open("outfile.txt",'w') as outfile: 
    for line in infile:
        if line.startswith('NUM,'):
            UNIT = line.strip().split(',')[1] 
            if UNIT not in wanted:
                for _ in xrange(4):
                    infile.next()
                continue

        outfile.write(line)

そしてセットで使います。メンバーシップを常に確認する方が高速です。

このアプローチでは、ファイル全体を一度に読み取ってリスト形式で処理する必要はありません。行ごとに、ファイルから読み取り、進み、新しいファイルに書き込みます。必要に応じて、出力ファイルを追加先のリストに置き換えることができます。

于 2012-08-24T21:35:08.593 に答える
0

リストを作成してもかまわず、"NUM"行が5行おきに来る場合は、次のことを試してみてください。

keep = []
for (i, v) in enumerate(lines[::5]):
    (num, current) = v.split(",")
    if current in wanted:
        keep.extend(lines[i*5:i*5+5])
于 2012-08-24T21:59:31.380 に答える
0

編集:反復中にアイテムを削除することはおそらく良い考えではありません。参照:反復中にリストからアイテムを削除する

infile = open("inputfile.txt",'r')
data = infile.readlines()
SKIP_LINES = 4
skip_until = False

result_data = []
for current_line, line in enumerate(data):
    if skip_until and skip_until < current_line:
        continue

    try:
        _, num = line.split(',')
    except ValueError:
        pass
    else:
       if num not in wanted:
           skip_until = current_line + SKIP_LINES
       else:
           result_data.append(line)

...そしてresult_dataあなたが望むものです。

于 2012-08-24T21:31:14.670 に答える
0

これを、リストを構築し、ループ中にリストから何かを削除するという観点から考えようとしないでください。その方法は狂気を導きます。

出力ファイルを直接書き込む方がはるかに簡単です。出力に書き込むかどうかを決定するたびに、入力ファイルの行をループします。

また、すべての行にコンマがあるわけではないという問題を回避するために、.partition代わりに を使用して行を分割してみてください。これは常に 3 つの項目を返します: コンマがある場合、取得します (最初のコンマの前、コンマ、コンマの後); それ以外の場合は、(全体、空の文字列、空の文字列) を取得します。wantedとにかく空の文字列が含まれないため、そこから最後のアイテムを使用できます。

skip_counter = 0
for line in infile:
    if line.partition(',')[2] not in wanted:
        skip_counter = 5
    if skip_counter:
        skip_counter -= 1
    else:
        outfile.write(line)
于 2012-08-25T00:31:35.833 に答える
0

コードにはいくつかの問題があります。たとえば、data_list定義さえされていません。の場合、そこから要素を取得listすることはできません。delあなただけができますpop。次に、enumerateと の直接インデックス アクセスの両方を使用しdataます。もreadlines必要ありません。

すべての行をメモリに保持しないようにすることをお勧めします。ここでは実際には必要ありません。たぶん(未テスト)のようなものを試してみてください:

with open('infile.txt') as fin, open('outfile.txt', 'w') as fout:
   for line in fin:
       if line.startswith('NUM,') and line.split(',')[1] not in wanted:
           for _ in range(4):
               fin.next()
       else:
           fout.write(line)
于 2012-08-24T21:36:00.840 に答える
0
import re
# find the lines that match NUM,XYZ
nums = re.compile('NUM,(?:' + '|'.join(['456','012']) + ")")
# find the three lines after a nums match
line_matches = breaks = re.compile('.*\n.*\n.*\n')
keeper = ''
for line in nums.finditer(data):
    keeper += breaks.findall( data[line.start():] )[0]

指定された文字列の結果は

NUM,456
FRUIT
DRINK
FOOD,BURGER

NUM,012
FRUIT
DRINK
FOOD,MEATBALL
于 2012-08-24T21:36:51.300 に答える