6

I have a string array:

string[] arr2 = { "/", "@", "&" };

I have another string (i.e. strValue). Is there a clean way to replace all instances of the array contents with a single value (i.e. an underscore)? So before:

strValue = "a/ new string, with some@ values&"

And after:

strValue = "a_ new string, with some_ values_"

I considered doing this:

strValue = strValue.Replace("/", "_");
strValue = strValue.Replace("@", "_");
strValue = strValue.Replace("&", "_");

But my array of characters to replace may become a lot bigger.

5
  • 2
    Put the replace in a loop or a method. Commented Nov 15, 2016 at 14:09
  • 7
    foreach(string replace in arr2){strValue = strValue.Replace(replace, "_");} Commented Nov 15, 2016 at 14:09
  • 1
    @AlfieGoodacre Was just about to comment almost that exact code, but you beat me to it. Nice. Commented Nov 15, 2016 at 14:09
  • But my array may get allot bigger - what other items can it include? Will the longer items contain shorter ones? Commented Nov 15, 2016 at 14:10
  • string.Join("_", strValue.Split(arr2)) Commented Nov 15, 2016 at 14:13

6 Answers 6

5

Instead of using the Replace over and over you could just write your own. This might even be a performance gain since you mentioned

But my array may get a lot bigger.

public string Replace(string original, char replacement, params char[] replaceables)
{
    StringBuilder builder = new StringBuilder(original.Length);
    HashSet<char> replaceable = new HashSet<char>(replaceables);
    foreach(Char character in original)
    {
        if (replaceable.Contains(character))
            builder.Append(replacement);
        else
            builder.Append(character);
    }
    return builder.ToString();
}

public string Replace(string original, char replacement, string replaceables)
{
    return Replace(original, replacement, replaceables.ToCharArray());
}

Can be called like this:

Debug.WriteLine(Replace("a/ new string, with some@ values&", '_', '/', '@', '&'));
Debug.WriteLine(Replace("a/ new string, with some@ values&", '_', new[] { '/', '@', '&' }));
Debug.WriteLine(Replace("a/ new string, with some@ values&", '_', existingArray));
Debug.WriteLine(Replace("a/ new string, with some@ values&", '_',"/@&"));

Output:

a_ new string, with some_ values_
a_ new string, with some_ values_
a_ new string, with some_ values_
a_ new string, with some_ values_

As @Sebi pointed out, this would also work as an extension method:

public static class StringExtensions
{
    public static string Replace(this string original, char replacement, params char[] replaceables)
    {
        StringBuilder builder = new StringBuilder(original.Length);
        HashSet<Char> replaceable = new HashSet<char>(replaceables);
        foreach (Char character in original)
        {
            if (replaceable.Contains(character))
                builder.Append(replacement);
            else
                builder.Append(character);
        }
        return builder.ToString();
    }

    public static string Replace(this string original, char replacement, string replaceables)
    {
        return Replace(original, replacement, replaceables.ToCharArray());
    }
}

Usage:

"a/ new string, with some@ values&".Replace('_', '/', '@', '&');
existingString.Replace('_', new[] { '/', '@', '&' });
// etc.
Sign up to request clarification or add additional context in comments.

1 Comment

Maybe this as extension method would be sexy :)
3

This is how i'd do it building a regex clause from the list of delimiters and replacing them with an underscore

string[] delimiters = { "/", "@", "&" };
string clause = $"[{string.Join("]|[", delimiters)}]";
string strValue = "a/ new string, with some@ values&";
Regex chrsToReplace = new Regex(clause);
string output = chrsToReplace.Replace(strValue, "_");

You'll probably want to encapsulate within if(delimiters.Any()), else it will crash if the array is empty

7 Comments

Not sure, but I don't think String Interpolation would work this way.
@ManfredRadlwimmer why would you say that without trying it out? it works fine for me
I stand corrected, just tried it, works fine. Sorry, my fault.
Would this work with string[] delimiters = { "/", "@", "&", "[", "\\" };?
@Henrik You can pass the array of delimiters through Regex.Escape if you have any characters with any special significance in regular expressions. delims = delims.Select(Regex.Escape);
|
2

Sure. Here's one approach:

var newString = arr2.Aggregate(strValue, (net, curr) => net.Replace(curr, "_"));

If you're only substituting individual characters and have large enough input sizes to need optimization, you can create a set from which to substitute:

var substitutions = new HashSet<char>() { '/', '@', '&' };
var strValue = "a/ new string, with some@ values&";
var newString = new string(strValue.Select(c => substitutions.Contains(c) ? '_' : c).ToArray());

Comments

0

Maybe not the fastest but the easiest would be a Select with a Contains.

Something like this : source.Select(c => blacklist.Contains(c) ? letter : c)

Demo on .NetFiddle.

using System;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var strValue = "a/ new string, with some@ values&";

        Console.WriteLine(strValue.Replace("/@&", '_'));
    }
}

public static class Extensions {
    public static string Replace(this string source, string blacklist, char letter) => 
        new string(source.Select(c => blacklist.Contains(c) ? letter : c).ToArray());
}

Comments

0

You can split your string with your list of string []:

string[] arr2 = { "/", "@", "&" };
string strValue = "a/ new string, with some@ values&";
string Output = null;
string[] split = strValue.Split(arr2, StringSplitOptions.RemoveEmptyEntries);
foreach (var item in split)
{
    Output += item + "_";
}
Console.WriteLine(Output);
//-> a_ new string, with some_ values_


Updated answer with @aloisdg comment (interesting article, thank you).

string[] arr2 = { "/", "@", "&" };
string strValue = "a/ new string, with some@ values&";
string[] split = strValue.Split(arr2, StringSplitOptions.RemoveEmptyEntries);

StringBuilder Output = new StringBuilder();
foreach (var item in split)
{
    Output.Append(item + "_");
}
Console.WriteLine(Output);
//-> a_ new string, with some_ values_

2 Comments

You may want to use StringBuilder (nice read)
Interesting! merci :)
0

You could use a foreach in a single line to achieve what you want:

arr2.ToList().ForEach(x => strValue = strValue.Replace(x, "_"));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.