我面前有一个在字符串中搜索90,000个GUID的问题。我需要获取每个GUID的所有实例。从技术上讲,我也需要更换它们,但这是另一个故事。
目前,我正在使用正则表达式单独搜索每一个。但是我想到通过一起搜索它们可以获得更好的性能。我已经阅读了过去的尝试并且从未使用过,但我想到我可以构建所有90,000个GUID并使用它来搜索。
或者,也许.NET中存在可以执行此操作的现有库。我突然想到,没有理由说我只能用一个巨大的正则表达式来获得良好的性能,但这似乎不起作用。
除此之外,也许我可以使用一些与GUID结构相关的聪明技巧来获得更好的结果。
这对我来说并不是一个至关重要的问题,但我想我可能会学到一些东西。
答案 0 :(得分:1)
我开发了一种替代大量字符串的方法,这可能很有用:
A better way to replace many strings - obfuscation in C#
另一种选择是使用正则表达式查找字符串中的所有GUID,然后遍历它们并检查每个GUID是否是GUID集的一部分。
基本示例,使用Dictionary
快速查找GUID:
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
答案 1 :(得分:1)
使用RegEx无法获得良好的性能,因为它的性能本质上很差。此外,如果所有GUID共享相同的格式,您只需要一个RegEx。并且regex.Replace(input, replacement);
会这样做。
如果你已经在内存中有guid列表,那么循环遍历该列表并像这样调用String.Replace
foreach(string guid in guids)
inputString.replace(guid, replacement);
答案 2 :(得分:1)
看看Rabin-Karp字符串搜索算法。它非常适合在字符串中进行多模式搜索:
答案 3 :(得分:0)
好的,这看起来不错。所以这里要清楚的是原始代码,在示例字符串上运行了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();