C#/ .NET中的可变字符串编辑

时间:2009-10-15 16:10:18

标签: c# .net

我想在.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: 更改样本以使每个'替换'需要具有不同的结果更明显。

8 个答案:

答案 0 :(得分:5)

如果您的代码确实如此简单,那么为什么不在stringStringBuilderRegex上使用其中一种内置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)

StringBuilderReplace”方法如何:

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;
}