0

文字列内で90,000個のGUIDを検索するという問題があります。各GUIDのすべてのインスタンスを取得する必要があります。技術的には、私もそれらを交換する必要がありますが、それは別の話です。

現在、正規表現を使用して、それぞれを個別に検索しています。しかし、それらをすべて一緒に検索することで、より良いパフォーマンスを得ることができると思いました。過去に試行について読んだことがあり、一度も使用したことがありませんが、90,000個のGUIDすべての試行を作成し、それを使用して検索できることに気付きました。

あるいは、これを実行できる既存のライブラリが.NETにある可能性があります。巨大な正規表現だけでは良いパフォーマンスが得られない理由はないのではないかと思いましたが、うまくいかないようです。

それ以外にも、より良い結果を得るためにGUID構造に関連して使用できる巧妙なトリックがいくつかあるかもしれません。

これは私にとってそれほど重大な問題ではありませんが、何かを学ぶことができるかもしれないと思いました。

4

4 に答える 4

1

しばらく前に、多数の文字列を置き換える方法を開発しました。これは便利な場合があります。

多くの文字列を置き換えるためのより良い方法-C#での難読化

もう1つのオプションは、正規表現を使用して文字列内のすべてのGUIDを検索し、それらをループして、それぞれがGUIDのセットの一部であるかどうかを確認することです。

DictionaryGUIDの高速ルックアップにを使用する基本的な例:

Dictionary<string, string> guids = new Dictionary<string, string>();
guids.Add("3f74a071-54fc-10de-0476-a6b991f0be76", "(replacement)");

string text = "asdf 3f74a071-54fc-10de-0476-a6b991f0be76 lkaq2hlqwer";

text = Regex.Replace(text, @"[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}", m => {
  string replacement;
  if (guids.TryGetValue(m.Value, out replacement)) {
    return replacement;
  } else {
    return m.Value;
  }
});

Console.WriteLine(text);

出力:

asdf (replacement) lkaq2hlqwer
于 2012-11-19T20:21:33.490 に答える
1

RegExのパフォーマンスは本質的に低いため、RegExでは良好なパフォーマンスが得られません。さらに、すべてのGUIDが同じ形式を共有している場合は、1つの正規表現のみが必要です。そしてregex.Replace(input, replacement);それをします。

GUIDのリストが既にメモリにある場合は、そのリストをループしてそのString.Replaceように呼び出すことで、パフォーマンスが向上します。

 foreach(string guid in guids)
     inputString.replace(guid, replacement);
于 2012-11-19T20:22:00.867 に答える
1

Rabin-Karp文字列検索アルゴリズムをご覧ください。文字列でのマルチパターン検索に最適です。

http://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_string_search_algorithm#Rabin.E2.80.93Karp_and_multiple_pattern_search

于 2012-11-19T20:25:51.417 に答える
0

OK、これはよさそうだ。したがって、ここで明確にするために、サンプル文字列で実行するのに65秒かかった元のコードがあります。

   var unusedGuids = new HashSet<Guid>(oldToNewGuid.Keys);

    foreach (var guid in oldToNewGuid) {
        var regex = guid.Key.ToString();

        if (!Regex.IsMatch(xml, regex))
             unusedGuids.Add(guid.Key);
        else
            xml = Regex.Replace(xml, regex, guid.Value.ToString());
    }

新しいコードは次のとおりで、6.7秒かかります。

var unusedGuids = new HashSet<Guid>(oldToNewGuid.Keys);

var guidHashes = new MultiValueDictionary<int, Guid>();

foreach (var guid in oldToNewGuid.Keys) {
    guidHashes.Add(guid.ToString().GetHashCode(), guid);
}

var indices = new List<Tuple<int, Guid>>();

const int guidLength = 36;

for (int i = 0; i < xml.Length - guidLength; i++) {
    var substring = xml.Substring(i, guidLength);

    foreach (var value in guidHashes.GetValues(substring.GetHashCode())) {
         if (value.ToString() == substring) {
        unusedGuids.Remove(value);
        indices.Add(new Tuple<int, Guid>(i, value));
        break;
         }
    }
}

var builder = new StringBuilder();

int start = 0;
for (int i = 0; i < indices.Count; i++) {
    var tuple = indices[i];
    var substring = xml.Substring(start, tuple.Item1 - start);
    builder.Append(substring);
    builder.Append(oldToNewGuid[tuple.Item2].ToString());
    start = tuple.Item1 + guidLength;
}

builder.Append(xml.Substring(start, xml.Length - start));

xml = builder.ToString();
于 2012-11-19T21:38:08.490 に答える