私はPython3を使用しています
さて、私はこのようにロックするファイルを手に入れました:
id:1
1
34
22
52
id:2
1
23
22
31
id:3
2
12
3
31
id:4
1
21
22
11
ファイルのこの部分だけを見つけて削除するにはどうすればよいですか?
id:2
1
23
22
31
私はこれを行うために多くのことを試みてきましたが、それを機能させることができません。
私はPython3を使用しています
さて、私はこのようにロックするファイルを手に入れました:
id:1
1
34
22
52
id:2
1
23
22
31
id:3
2
12
3
31
id:4
1
21
22
11
ファイルのこの部分だけを見つけて削除するにはどうすればよいですか?
id:2
1
23
22
31
私はこれを行うために多くのことを試みてきましたが、それを機能させることができません。
シーケンスを削除する決定に ID が使用されるか、それとも決定に値のリストが使用されますか?
ID番号がキーである辞書を作成でき(後でソートするためにintに変換されます)、次の行はキーの値である文字列のリストに変換されます。次に、キー 2 のアイテムを削除し、キーでソートされたアイテムをトラバースして、新しい id:key と文字列のフォーマットされたリストを出力できます。
または、順序が保護されているリストのリストを作成できます。ID のシーケンスを保護する (つまり、番号を付け直さない) 場合は、内側のリストで id:n を覚えておくこともできます。
これは、適度なサイズのファイルに対して実行できます。ファイルが巨大な場合は、コピー元をコピー先にコピーし、不要なシーケンスをその場でスキップする必要があります。最後のケースは、小さなファイルでもかなり簡単です。
[明確化後に追加]
そのような多くの場合に役立つ次のアプローチを学ぶことをお勧めします。これは、ある状態から別の状態への遷移にバインドされたアクションを実装する、いわゆる有限オートマトンを使用します ( Mealy マシンを参照)。
ここでは、テキスト行が入力要素です。ここでは、コンテキスト ステータスを表すノードに番号が付けられています。(私の経験では、それらに名前を付ける価値はありません。馬鹿げた数字のままにしておいてください。) ここでは 2 つの状態のみが使用されておりstatus
、ブール変数で簡単に置き換えることができます。ただし、ケースがより複雑になると、別のブール変数の導入につながり、コードでエラーが発生しやすくなります。
if status == number
最初はコードが非常に複雑に見えるかもしれませんが、それぞれを個別に考えることができることを知っていれば、理解するのはかなり簡単です。これは、前の処理をキャプチャした前述のコンテキストです。最適化しようとしないでください。コードをそのままにしてください。実際には後で人間がデコードすることができ、 Mealy マシンの例に似た絵を描くことができます。もしそうなら、それははるかに理解できます。
必要な機能は少し一般化されています。無視されたセクションのセットを最初の引数として渡すことができます。
import re
def filterSections(del_set, fname_in, fname_out):
'''Filtering out the del_set sections from fname_in. Result in fname_out.'''
# The regular expression was chosen for detecting and parsing the id-line.
# It can be done differently, but I consider it just fine and efficient.
rex_id = re.compile(r'^id:(\d+)\s*$')
# Let's open the input and output file. The files will be closed
# automatically.
with open(fname_in) as fin, open(fname_out, 'w') as fout:
status = 1 # initial status -- expecting the id line
for line in fin:
m = rex_id.match(line) # get the match object if it is the id-line
if status == 1: # skipping the non-id lines
if m: # you can also write "if m is not None:"
num_id = int(m.group(1)) # get the numeric value of the id
if num_id in del_set: # if this id should be deleted
status = 1 # or pass (to stay in this status)
else:
fout.write(line) # copy this id-line
status = 2 # to copy the following non-id lines
#else ignore this line (no code needed to ignore it :)
elif status == 2: # copy the non-id lines
if m: # the id-line found
num_id = int(m.group(1)) # get the numeric value of the id
if num_id in del_set: # if this id should be deleted
status = 1 # or pass (to stay in this status)
else:
fout.write(line) # copy this id-line
status = 2 # to copy the following non-id lines
else:
fout.write(line) # copy this non-id line
if __name__ == '__main__':
filterSections( {1, 3}, 'data.txt', 'output.txt')
# or you can write the older set([1, 3]) for the first argument.
ここでは、元の番号が指定された出力 ID 行です。セクションの番号を付け直したい場合は、簡単な変更で実行できます。コードを試して、詳細を尋ねてください。
有限オートマトンのパワーは限られていることに注意してください。ネストされたペア構造 (括弧など) をキャプチャできないため、通常のプログラミング言語では使用できません。
PS 7000 行は、実際にはコンピューターの観点からは小さなファイルです ;)
各行を文字列の配列に読み込みます。インデックス番号は行番号 - 1 です。行を読み取る前に、行が「id:2」と等しいかどうかを確認してください。はいの場合、行が「id:3」に等しくなるまで行の読み取りを停止します。行を読み取った後、ファイルをクリアし、配列の最後まで配列をファイルに書き戻します。これは最も効率的な方法ではないかもしれませんが、うまくいくはずです。
その間に干渉する値がない場合、これは機能します....
import fileinput
...
def deleteIdGroup( number ):
deleted = False
for line in fileinput.input( "testid.txt", inplace = 1 ):
line = line.strip( '\n' )
if line.count( "id:" + number ): # > 0
deleted = True;
elif line.count( "id:" ): # > 0
deleted = False;
if not deleted:
print( line )
編集:
申し訳ありませんが、これは id:2 と id:20 を削除します ... 最初の if チェック -行 == "id:" + 番号