Reputation: 1730
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
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
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
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
Reputation:
Remove the foreach
and replace with a for
loop from 0 to item.Count
. This article will help, hopefully.
Upvotes: 0
Reputation: 355
Look this answer: answer
But in this code put your characteres:
IDictionary<string,string> map = new Dictionary<string,string>()
{
{"É", = "@"},
{"Ä", = "["},
{"Ö", = "\\"},
...
};
Upvotes: 2
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