Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace multiple characters in a C# string

Tags:

string

c#

.net

You can use a replace regular expression.

s/[;,\t\r ]|[\n]{2}/\n/g
  • s/ at the beginning means a search
  • The characters between [ and ] are the characters to search for (in any order)
  • The second / delimits the search-for text and the replace text

In English, this reads:

"Search for ; or , or \t or \r or (space) or exactly two sequential \n and replace it with \n"

In C#, you could do the following: (after importing System.Text.RegularExpressions)

Regex pattern = new Regex("[;,\t\r ]|[\n]{2}");
pattern.Replace(myString, "\n");

If you are feeling particularly clever and don't want to use Regex:

char[] separators = new char[]{' ',';',',','\r','\t','\n'};

string s = "this;is,\ra\t\n\n\ntest";
string[] temp = s.Split(separators, StringSplitOptions.RemoveEmptyEntries);
s = String.Join("\n", temp);

You could wrap this in an extension method with little effort as well.

Edit: Or just wait 2 minutes and I'll end up writing it anyway :)

public static class ExtensionMethods
{
   public static string Replace(this string s, char[] separators, string newVal)
   {
       string[] temp;

       temp = s.Split(separators, StringSplitOptions.RemoveEmptyEntries);
       return String.Join( newVal, temp );
   }
}

And voila...

char[] separators = new char[]{' ',';',',','\r','\t','\n'};
string s = "this;is,\ra\t\n\n\ntest";

s = s.Replace(separators, "\n");

You could use Linq's Aggregate function:

string s = "the\nquick\tbrown\rdog,jumped;over the lazy fox.";
char[] chars = new char[] { ' ', ';', ',', '\r', '\t', '\n' };
string snew = chars.Aggregate(s, (c1, c2) => c1.Replace(c2, '\n'));

Here's the extension method:

public static string ReplaceAll(this string seed, char[] chars, char replacementCharacter)
{
    return chars.Aggregate(seed, (str, cItem) => str.Replace(cItem, replacementCharacter));
}

Extension method usage example:

string snew = s.ReplaceAll(chars, '\n');

This is the shortest way:

myString = Regex.Replace(myString, @"[;,\t\r ]|[\n]{2}", "\n");

Ohhh, the performance horror! The answer is a bit outdated, but still...

public static class StringUtils
{
    #region Private members

    [ThreadStatic]
    private static StringBuilder m_ReplaceSB;

    private static StringBuilder GetReplaceSB(int capacity)
    {
        var result = m_ReplaceSB;

        if (null == result)
        {
            result = new StringBuilder(capacity);
            m_ReplaceSB = result;
        }
        else
        {
            result.Clear();
            result.EnsureCapacity(capacity);
        }

        return result;
    }


    public static string ReplaceAny(this string s, char replaceWith, params char[] chars)
    {
        if (null == chars)
            return s;

        if (null == s)
            return null;

        StringBuilder sb = null;

        for (int i = 0, count = s.Length; i < count; i++)
        {
            var temp = s[i];
            var replace = false;

            for (int j = 0, cc = chars.Length; j < cc; j++)
                if (temp == chars[j])
                {
                    if (null == sb)
                    {
                        sb = GetReplaceSB(count);
                        if (i > 0)
                            sb.Append(s, 0, i);
                    }

                    replace = true;
                    break;
                }

            if (replace)
                sb.Append(replaceWith);
            else
                if (null != sb)
                    sb.Append(temp);
        }

        return null == sb ? s : sb.ToString();
    }
}

Strings are just immutable char arrays

You just need to make it mutable:

  • either by using StringBuilder
  • go in the unsafe world and play with pointers (dangerous though)

and try to iterate through the array of characters the least amount of times. Note the HashSet here, as it avoids to traverse the character sequence inside the loop. Should you need an even faster lookup, you can replace HashSet by an optimized lookup for char (based on an array[256]).

Example with StringBuilder

public static void MultiReplace(this StringBuilder builder, 
    char[] toReplace, 
    char replacement)
{
    HashSet<char> set = new HashSet<char>(toReplace);
    for (int i = 0; i < builder.Length; ++i)
    {
        var currentCharacter = builder[i];
        if (set.Contains(currentCharacter))
        {
            builder[i] = replacement;
        }
    }
}

Edit - Optimized version

public static void MultiReplace(this StringBuilder builder, 
    char[] toReplace,
    char replacement)
{
    var set = new bool[256];
    foreach (var charToReplace in toReplace)
    {
        set[charToReplace] = true;
    }
    for (int i = 0; i < builder.Length; ++i)
    {
        var currentCharacter = builder[i];
        if (set[currentCharacter])
        {
            builder[i] = replacement;
        }
    }
}

Then you just use it like this:

var builder = new StringBuilder("my bad,url&slugs");
builder.MultiReplace(new []{' ', '&', ','}, '-');
var result = builder.ToString();