我想在.NET应用程序中就地编辑字符串。我知道StringBuilder
允许我进行就地附加,插入和替换,但它不允许这样做的简单方法:
while (script.IndexOf("@Unique", StringComparison.InvariantCultureIgnoreCase) != -1)
{
int Location = script.IndexOf("@Unique", StringComparison.InvariantCultureIgnoreCase);
script = script.Remove(Location, 7);
script = script.Insert(Location, Guid.NewGuid().ToString());
}
由于IndexOf
中没有StringBuilder
。有没有人有一种有效的方法来进行文本信息的就地编辑?
编辑#1: 更改样本以使每个'替换'需要具有不同的结果更明显。
答案 0 :(得分:5)
如果您的代码确实如此简单,那么为什么不在string
,StringBuilder
或Regex
上使用其中一种内置Replace
方法?
编辑后的评论......
您可以使用one of the overloads of Regex.Replace
that takes a MatchEvaluator
参数替换每个匹配项:
string foo = "blah blah @Unique blah @Unique blah blah @Unique blah";
// replace each occurrence of "@Unique" with a separate guid
string bar = Regex.Replace(foo, "@Unique",
new MatchEvaluator(m => Guid.NewGuid().ToString()),
RegexOptions.IgnoreCase));
答案 1 :(得分:2)
StringBuilder
“Replace”方法如何:
StringBuilder script;
script.Replace("@Unique", GetGuidString());
答案 2 :(得分:2)
你要做多少次更换?
如果它不是四个数字,那么只接受新的字符串实例,你可能会过早地优化......
另一个解决方案......在“@uniqueID”上拆分然后重新加入StringBuilder,为每次迭代添加你的分隔符。
答案 3 :(得分:1)
StringBuilder是为了让你可以轻松添加它,但在权衡中很难在其中搜索 - 特别是,索引它更难(即更慢)。 如果您需要“就地”修改某些字符,最好对结果字符串进行修改。
但很难从你的问题中知道对你来说什么是正确的答案,我的感觉是你不应该在StringBuilder中进行就地替换,而问题是在其他地方/你做了别的错误。
答案 4 :(得分:1)
用户Dennis提供了IndexOf extension method for StringBuilder。有了这个,您应该能够以这种方式使用StringBuilder。
答案 5 :(得分:0)
您可以使用字符串拆分来有效地执行此操作吗?
类似的东西:
var sections = "a-@Unique-b-@Unique-c".Split(new string[] { "@Unique" }, StringSplitOptions.None);
int i;
StringBuilder builder = new StringBuilder();
for(i = 0; i < sections.Length - 1; i++)
{
builder.Append(sections[i]);
builder.Append(Guid.NewGuid().ToString());
}
builder.Append(sections[i]);
Console.WriteLine(builder.ToString());
Console.ReadKey(true);
答案 6 :(得分:0)
复杂但应该是高性能解决方案
public StringBuilder Replace(this StringBuilder sb, string toReplace, Func<string> getReplacement)
{
for (int i = 0; i < sb.Length; i++)
{
bool replacementFound = true;
for (int toReplaceIndex = 0; toReplaceIndex < toReplace.Length; toReplaceIndex++)
{
int sbIndex = toReplaceIndex + i;
if (sbIndex < sb.Length)
{
return sb;
}
if (sb[sbIndex] != toReplace[toReplaceIndex])
{
replacementFound = false;
break;
}
}
if (replacementFound)
{
string replacement = getReplacement();
// reuse the space of the toReplace string
for (int replacementIndex = 0; replacementIndex < toReplace.Length && replacementIndex < replacement.Length; replacementIndex++)
{
int sbIndex = replacementIndex + i;
sb[sbIndex] = replacement[i];
}
// remove toReplace string remainders
if (replacement.Length < toReplace.Length)
{
sb.Remove(i + replacement.Length, replacement.Length - toReplace.Length)
}
// insert chars not yet inserted
if (replacement.Length > toReplace.Length)
{
sb.Insert(i + toReplace.Length, replacement.ToCharArray(toReplace.Length, toReplace.Length - replacement.Length));
}
}
}
return sb;
}
用例
var sb = new StringBuilder(script);
script = sb.Replace("@Unique", () => Guid.NewGuid().ToString()).ToString();
答案 7 :(得分:-4)
您将需要使用非托管代码块 就像声明一个指向你的字符串的指针并在内存中操作它一样简单。
实施例
unsafe
{
char* ip;
ip = &to_your_string;
}