不要在一个巨大的字符串中进行替换(这意味着您需要移动大量数据),而是遍历该字符串并一次替换一个标记。
创建一个包含每个标记的下一个索引的列表,找到第一个标记,然后将文本复制到该标记到结果,然后替换该标记。然后检查该标记下一次出现在字符串中的位置,以使列表保持最新。重复此操作,直到找不到更多标记,然后将剩余文本复制到结果中。
我做了一个简单的测试,这个方法在208毫秒内对1000000个字符串进行了125000次替换。
Token 和 TokenList 类:
public class Token {
public string Text { get; private set; }
public string Replacement { get; private set; }
public int Index { get; set; }
public Token(string text, string replacement) {
Text = text;
Replacement = replacement;
}
}
public class TokenList : List<Token>{
public void Add(string text, string replacement) {
Add(new Token(text, replacement));
}
private Token GetFirstToken() {
Token result = null;
int index = int.MaxValue;
foreach (Token token in this) {
if (token.Index != -1 && token.Index < index) {
index = token.Index;
result = token;
}
}
return result;
}
public string Replace(string text) {
StringBuilder result = new StringBuilder();
foreach (Token token in this) {
token.Index = text.IndexOf(token.Text);
}
int index = 0;
Token next;
while ((next = GetFirstToken()) != null) {
if (index < next.Index) {
result.Append(text, index, next.Index - index);
index = next.Index;
}
result.Append(next.Replacement);
index += next.Text.Length;
next.Index = text.IndexOf(next.Text, index);
}
if (index < text.Length) {
result.Append(text, index, text.Length - index);
}
return result.ToString();
}
}
使用示例:
string text =
"This is a text with some words that will be replaced by tokens.";
var tokens = new TokenList();
tokens.Add("text", "TXT");
tokens.Add("words", "WRD");
tokens.Add("replaced", "RPL");
string result = tokens.Replace(text);
Console.WriteLine(result);
Output:
This is a TXT with some WRD that will be RPL by tokens.
Note:此代码不处理重叠标记。例如,如果您有标记“pineapple”和“apple”,则代码将无法正常工作。
Edit:
要使代码能够处理重叠标记,请替换此行:
next.Index = text.IndexOf(next.Text, index);
用这个代码:
foreach (Token token in this) {
if (token.Index != -1 && token.Index < index) {
token.Index = text.IndexOf(token.Text, index);
}
}