0

誰かが潜在的な文字列の置き換えに適したアイデアを持っていますか?

さまざまな長さのさまざまな長さの文字列のコレクションがあり、一部の文字列では、エンコードされた16進値の特別な置換必要になる場合があります(例:= 0A、%20 ...など)

各文字列の「置換」(複数ある場合もあります)は、適切なエスケープされた16進値を検出するために正規表現によって処理されます。

どちらがより効率的でしょうか?

  1. コレクション内のすべての文字列に対して置換を実行するだけで、必要なすべての置換が行われるように総当たり攻撃を行うことができます。

  2. 置換が必要な場合にテストを実行し、それを必要とするストリングに対してのみ置換を実行します。

私はC#で働いています。

アップデート

回答とコメントからの少しの追加情報。

これは主に、QRコードから読み込まれるVCARD処理用です

現在、キャプチャグループを使用して、VCARDの各KEY; PARAMETERS:VALUEからKEY、PARAMETERS、およびVALUEを取得する正規表現があります。

私はv2.1と3.0をサポートしているので、エンコーディングとラインフォールディングは非常に異なるため、デコードする前にバージョンを知る必要があります。

今では、正規表現全体を実行してバージョンを取得し、適切な置換をテキストのvcardブロック全体に適用してから、正規表現を再実行することは意味がありません。

私にとっては、キャプチャグループをロードしてからバージョンを取得し、一致するたびに適切なデコード置換を行う方が理にかなっています。

4

4 に答える 4

1

置換するだけの場合、置換が行う追加のチェックのために、一致しない場合は実行がわずかに遅くなります(例)

if (replacement == null)
{
    throw new ArgumentNullException("replacement");
}

一致が見つからない場合、Regex.Replace は入力を返すため、メモリの問題はありません。

Match match = regex.Match(input, startat);
if (!match.Success)
{
    return input;
}

一致する場合、regex.Match は、実行時に 1 回、置換時に 2 回発生します。これは、Check and Replace の実行が遅くなることを意味します。

したがって、結果はに基づいています

  • 多くの試合または多くのミスを期待していますか?
  • Regex.Match一致する場合、が 2 回実行されるという事実は、追加のパラメーター チェックをどのように圧倒しますか? 私の推測では、おそらくそうなるでしょう。
于 2012-06-01T22:42:29.513 に答える
0

ルックフォワード チェックを備えた非常に特殊なレクサーのラインに沿って何かを使用できます。

outputBuffer := new StringBuilder
index := 0
max := input.Length
while index < max
    if input[ index ] == '%'
    && IsHexDigit( input[ index + 1 ] )
    && IsHexDigit( input[ index + 2 ] )
        outputBuffer.Append( ( char )int.Parse( input.Substring( index + 1, 2 )
        index += 3
        continue
    else
        outputBuffer.Append( input[ index ] )
        index ++;
        continue
于 2012-06-02T00:23:10.053 に答える
0

文字列置換を使用する場合は、string.Replace よりもStringBuilder.Replaceを使用する方がよい場合があります。(置換中に多くの一時文字列を作成しません....)

于 2012-06-02T05:42:06.630 に答える
0

(質問者に代わって投稿) .

声をかけてくれた何人かの素晴らしい人々からインスピレーションを得て、問題のコードを分離してテストすることができました.

どちらの場合も、vcard の各「行」の分割を処理する Parser Regex と、エンコードされた 16 進数のキャプチャを処理する Decode Regex があります。

string.Replace を使用するかどうかに関係なく、潜在的な置換 16 進コードを取得するには、Decode Regex に依存する必要があることに気付きました。

数が変化するかどうかを確認するために、いくつかの異なるシナリオを実行しました。以下を含む: Regex MatchCollection をディクショナリにキャストして Match オブジェクトの複雑さを取り除き、Decoding regex を単純な文字列の古い文字列値と新しい文字列値を持つ個別の単純な匿名オブジェクトのコレクションに射影します。

最後に、String.Replace を使用してテストをどのようにマッサージしても、それに近づくことはできましたが、Decoded Regex に置き換えさせるよりも常に遅くなりました。

最も近いものは、速度の約 12% の差でした。

最終的に、好奇心旺盛な人にとっては、これが勝利のコード ブロックになったものです

    var ParsedCollection = Parser.Matches(UnfoldedEncodeString).Cast<Match>().Select(m => new
    {
      Field = m.Groups["FIELD"].Value,
      Params = m.Groups["PARAM"].Captures.Cast<Capture>().Select(c => c.Value),
      Encoding = m.Groups["ENCODING"].Value,
      Content = m.Groups["ENCODING"].Value.FirstOrDefault == 'Q' ? QuotePrintableDecodingParser.Replace(m.Groups["CONTENT"].Value, me => Convert.ToChar(Convert.ToInt32(me.Groups["HEX"].Value, 16)).ToString()) : m.Groups["CONTENT"].Value,
      Base64Content = ((m.Groups["ENCODING"].Value.FirstOrDefault() == 'B') ? Convert.FromBase64String(m.Groups["CONTENT"].Value.Trim()) : null)
    });

ワンショットで必要なものをすべて与えてくれます。すべてのフィールド、それらの値、任意のパラメーター、および 2 つの最も一般的なエンコーディングがデコードされ、適切にパッケージ化された匿名オブジェクトに投影されます。

プラス面としては、文字列から解析およびデコードされた匿名オブジェクトまでわずか 1000 ナノ秒強です (LINQ および拡張メソッドに感謝します) (約 4,000 の長さの VCARD を使用した 100,000 回のテストに基づく)。

于 2017-11-01T21:01:05.613 に答える