Editing Mutable String in C # /. NET

I want to take and edit a string in place in a .NET application. I know it StringBuilder

allows me to do in-place add, insert and replace, but that doesn't make it easy to do things like this:

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

      

As not IndexOf

in StringBuilder

. Does anyone have an efficient way to edit text information in place?

Edit # 1: Modified sample to make it more obvious that each "replacement" should have a different result.

+2


source to share


8 answers


If your code is really that simple, why not just use one of the built-in methods Replace

, either on string

, StringBuilder

or Regex

?

EDIT FOLLOWING COMMENT ...



You can replace each occurrence with a distinct value using one of the overloads Regex.Replace

that takes an argumentMatchEvaluator

:

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

      

+5


source


How about the StringBuilder

" Replace " method:



StringBuilder script;
script.Replace("@Unique", GetGuidString());

      

+2


source


How many changes will you make?

If it's not four digits, but just accept new string instances, you might be prematurely optimizing ...

Another solution ... Divide by "@uniqueID" then join the StringBuilder adding your seperator for each iteration.

+2


source


The StringBuilder is designed in such a way that you can easily add to it, but with a tradeoff that's hard to find in it - and all the more difficult (i.e. slower) to index it. If you need to change some characters "in place", it is best to do so in the resulting string.

But from your question it's hard to figure out which is the correct answer for you, I feel like you don't need to replace the place in place in the StringBuilder and the problem is elsewhere / you are doing something else wrong.

+1


source


User Dennis provided an IndexOf extension method for StringBuilder . Thus, you should be able to use StringBuilder this way.

+1


source


Can you use line splitting to do this efficiently?

Something like:

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

      

0


source


but should be an effective solution

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

      

use case

var sb = new StringBuilder(script);

script = sb.Replace("@Unique", () => Guid.NewGuid().ToString()).ToString();

      

0


source


You will need to use an unmanaged block of code. As easy as declaring a pointer to your string and manipulating it in memory.

Example

unsafe
{
  char* ip;
  ip = &to_your_string;
}

      

-4


source







All Articles