Shiju Shaji
Shiju Shaji

Reputation: 1730

How to replace characters in a string?

I want to replace characters in a string content in file. Below Dictionary shows the Key as unwanted character and i need to replace with the value in the Dictionary.

Dictionary<string, string> unwantedCharacters = new Dictionary<string, string>();
        unwantedCharacters["É"] = "@";
        unwantedCharacters["Ä"] = "[";
        unwantedCharacters["Ö"] = "\\";
        unwantedCharacters["Å"] = "]";
        unwantedCharacters["Ü"] = "^";
        unwantedCharacters["é"] = "`";
        unwantedCharacters["ä"] = "{";
        unwantedCharacters["ö"] = "|";
        unwantedCharacters["å"] = "}";
        unwantedCharacters["ü"] = "~";

Here is the code i currently using,Feel like its taking too much execution time..

 for (int index = 0; index < fileContents.Length; index++)
        {
            foreach (KeyValuePair<string, string> item in unwantedCharacters)
            {
                if (fileContents.IndexOf(item.Key) > -1)
                {
                    fileContents = fileContents.Replace(item.Key, item.Value); // Replacing straight characters
                }
            }
        }

ie,Looping in two levels.. Any other ways implement this..Any help will be appreciated

Upvotes: 0

Views: 573

Answers (6)

Ryszard Dżegan
Ryszard Dżegan

Reputation: 25414

In order to replace many characters in string, consider to use StringBuilder Class. Replacing one character in string causes in creation of entirly new string so it is highly inefficient. Try the below:

var sb = new StringBuilder(fileContents.Length);

foreach (var c in fileContents)
    sb.Append(unwantedCharacters.ContainsKey(c) ? unwantedCharacters[c] : c);

fileContents = sb.ToString();

I assumed here, that your dictionary contains characters (Dictionary<char, char>). It it is a case, just comment and I will edit the solution.

I also assumed, that fileContents is a string.

You can also use LINQ instead of StringBuilder:

var fileContentsEnumerable = from c in fileContents
                             select unwantedCharacters.ContainsKey(c) ? unwantedCharacters[c] : c;

fileContents = new string(fileContentsEnumerable.ToArray());

Upvotes: 2

Rawling
Rawling

Reputation: 50104

Since you're not modifying the length of the string, if you make unwantedCharacters a Dictionary<char, char> rather than <string, string>, you can do the following:

var charArray = fileContents.ToCharArray();
for (int i = 0; i < charArray.Length; i++)
{
    char replacement;
    if (unwantedCharacters.TryGetValue(charArray[i], out replacement))
        charArray[i] = replacement;
}
fileContents = new string(charArray);

Performance is O(n) in releation to the length of the input string.

Upvotes: 3

Mau
Mau

Reputation: 14468

You want to build a filter. You process the contents of the file, and do the substitution while you process it.

Something like this:

        using(StreamReader reader = new StreamReader("filename"))
        using (StreamWriter writer = new StreamWriter("outfile"))
        {
            char currChar = 0;
            while ((currChar = reader.Read()) >= 0)
            {
                char outChar = unwantedCharacters.ContainsKey(currChar)
                                   ? unwantedCharacters[currChar]
                                   : (char) currChar;
                writer.Write(outChar);
            }
        }

You can use a memeory stream if your data is in memory, or a loop through fileContents is that's a string or char array.

This solution is O(n) where n is the length of the file, thanks to the dictionary (note that you could use a simple sparse array instead of the dictionary and you would gain quite a bit of speed).

Do not iterate through the dictionary as other suggest as each substitution is O(n) so you end up with a total time of O(n*d), d being the dictionary size, as you have to go through the file many times.

Upvotes: 1

user1945782
user1945782

Reputation:

Remove the foreach and replace with a for loop from 0 to item.Count. This article will help, hopefully.

Upvotes: 0

user1848942
user1848942

Reputation: 355

Look this answer: answer

But in this code put your characteres:

IDictionary<string,string> map = new Dictionary<string,string>()
    {
       {"É", = "@"},
       {"Ä", = "["},
       {"Ö", = "\\"},
       ...
    };

Upvotes: 2

Ravi Y
Ravi Y

Reputation: 4376

It seems fileContents is a string value here. You could simply call replace on the string.

foreach (KeyValuePair<string, string> item in unwantedCharacters)
{
    fileContents = fileContents.Replace(item.Key, item.Value); 
}

Upvotes: 2

Related Questions