2

特定のパターンの複数の部分文字列を置き換える必要がある大きな文字列 (約 25M 文字) があります。

Frame 1
0,0,0,0,0,1,2,34,0
0,1,2,3,34,12,3,4,0

...........

Frame 2
0,0,0,0,0,1,2,34,0
0,1,2,3,34,12,3,4,0

...........

Frame 7670
0,0,0,0,0,1,2,34,0
0,1,2,3,34,12,3,4,0

...........

削除する必要がある部分文字列は「フレーム #」で、約 7670 回発生します。セル配列を使用して、strrep で複数の検索文字列を指定できます

strrep(text,{'Frame 1','Frame 2',..,'Frame 7670'},';')

ただし、それはセル配列を返します。各セルには、入力セルの1つの対応する部分文字列が変更された元の文字列があります。

regexprep を使用する以外に、文字列から複数の部分文字列を置き換える方法はありますか? strrep よりかなり遅いことに気付いたので、それを避けようとしています。

regexprep を使用すると、次のようになります。

regexprep(text,'Frame \d*',';')

25MB の文字列の場合、すべてのインスタンスを置き換えるのに約 47 秒かかります。

EDIT 1 : 同等の regexprep コマンドを追加しました

EDIT 2 : 参照用の文字列のサイズ、部分文字列の出現回数、および regexprep の実行タイミングを追加

4

3 に答える 3

2

わかりました、最終的に私は問題を回避する方法を見つけました。部分文字列を変更するために regexprep を使用する代わりに、'Frame' 部分文字列を削除します (空白を含みますが、数字は含みません)。

rawData = strrep(text,'Frame ','');

これにより、次のような結果になります。

1
0,0,0,0,0,1,2,34,0
0,1,2,3,34,12,3,4,0

...........

2
0,0,0,0,0,1,2,34,0
0,1,2,3,34,12,3,4,0

...........

7670
0,0,0,0,0,1,2,34,0
0,1,2,3,34,12,3,4,0

...........

次に、再度 strrep を使用して、すべてのコンマ (,) と改行文字 (\n) をセミコロン (;) に変更し、すべての数値を含む大きなベクトルを作成します。

rawData = strrep(rawData,sprintf('\r\n'),';');
rawData = strrep(rawData,';;',';');
rawData = strrep(rawData,';;',';');
rawData = strrep(rawData,',',';');
rawData = textscan(rawData,'%f','Delimiter',';');

次に、不要な数字 (1,2,...,7670) を削除します。これらは配列内の特定の位置にあるためです (各フレームには特定の数の数字が含まれています)。

rawData{1}(firstInstance:spacing:lastInstance)=[];

そして、私は自分の操作を続けます。追加の strrep と配列からの値の削除は、同等の regexprep よりもはるかに高速であるようです。regexprep を使用した 25M 文字の文字列では、操作全体を約 47 インチで実行できますが、この回避策では 5 インチしかかかりません!

これが何らかの形で役立つことを願っています。

于 2013-11-15T10:27:29.433 に答える
1

textscanこれは、非常に高速であることが知られているのみを使用して実行できると思います。行が取り除かれている'CommentStyle'ことを指定します。'Frame #'これは、これらの'Frame #'行が独自の行にあるためにのみ機能する場合があります。このコードは生データを 1 つの大きなベクトルとして返します。

s = textscan(text,'%f','CommentStyle','Frame','Delimiter',',');
s = s{:}

各フレームに含まれる要素の数を知りたい場合や、データを行列に再形成する場合もあります。textscanもう一度 (または上記の前に) を使用して、最初のフレームのデータだけを取得できます。

f1 = textscan(text,'%f','CommentStyle','Frame 1','Delimiter',',');
f1 = s{:}

実際、最初の行の要素だけが必要な場合は、これを使用できます。

l1 = textscan(text,'%f,','CommentStyle','Frame 1')
l1 = l1{:}

ただし、もう 1 つの優れた点は、FID を取得するためtextscanだけに使用して、ファイルを直接読み込むことができることです (現在、他の手段を使用しているようです) 。fopenしたがって、文字列データtextはメモリ内にある必要はありません。

于 2013-11-15T17:05:44.093 に答える