I'm using NET 2.0 and WinForms.
Currently, I need a code to replace a string with another one in a given text, but in the text it should only look for whole words. What I mean is:
string name = @"COUNTER = $40
CLOCK_COUNTER = $60";
name = name.Replace("COUNTER", "COUNT");
It should only replace the first instance of COUNTER
with COUNT
, because that's whole word. However, it seems string.Replace
does not take whole word into consideration.
Please don't recommend regex. I have already tried it, and it's too slow for my needs. I need something very fast and efficient. How could I accomplish this?
string input = @"COUNTER = $40
CLOCK_COUNTER = $60";
string name = Regex.Replace(input, @"\bCOUNTER\b", "COUNT");
\b
marks word boundries.
The only alternative to Regex is to develop your own algorithm! Search for "COUNTER" and test the previous and following character for not being a word character.
EDIT:
Here is my solution as extension method:
public static class ReplaceWordNoRegex
{
private static bool IsWordChar(char c)
{
return Char.IsLetterOrDigit(c) || c == '_';
}
public static string ReplaceFullWords(this string s, string oldWord, string newWord)
{
if (s == null) {
return null;
}
int startIndex = 0;
while (true) {
int position = s.IndexOf(oldWord, startIndex);
if (position == -1) {
return s;
}
int indexAfter = position + oldWord.Length;
if ((position == 0 || !IsWordChar(s[position - 1])) && (indexAfter == s.Length || !IsWordChar(s[indexAfter]))) {
s = s.Substring(0, position) + newWord + s.Substring(indexAfter);
startIndex = position + newWord.Length;
} else {
startIndex = position + oldWord.Length;
}
}
}
}
EDIT #2:
And here is a solution with StringBuilder.
public static string ReplaceFullWords(this string s, string oldWord, string newWord)
{
if (s == null) {
return null;
}
int startIndex = 0; // Where we start to search in s.
int copyPos = 0; // Where we start to copy from s to sb.
var sb = new StringBuilder();
while (true) {
int position = s.IndexOf(oldWord, startIndex);
if (position == -1) {
if (copyPos == 0) {
return s;
}
if (s.Length > copyPos) { // Copy last chunk.
sb.Append(s.Substring(copyPos, s.Length - copyPos));
}
return sb.ToString();
}
int indexAfter = position + oldWord.Length;
if ((position == 0 || !IsWordChar(s[position - 1])) && (indexAfter == s.Length || !IsWordChar(s[indexAfter]))) {
sb.Append(s.Substring(copyPos, position - copyPos)).Append(newWord);
copyPos = position + oldWord.Length;
}
startIndex = position + oldWord.Length;
}
}
Small workaround:
string name = @"COUNTER = $40
CLOCK_COUNTER = $60";
name=" "+name;
name = name.Replace(" COUNTER ", " COUNT ");
Main idea that you have to mark the word you're going to replace with some sort of symbols that other words that you do not want to replace have not
I think you cannot achieve that string replace any faster (I'm talking about developing time) than by RegExp
string input = @"COUNTER = $40 CLOCK_COUNTER = $60";
string pattern = @"\bCOUNTER\b";
string replacement = "COUNT";
var regex = new Regex(pattern,RegexOptions.Compiled);
string result = regex.Replace(input, replacement);
Adding RegexOptions.Compiled makes it faster if you intend to reuse
-------------------UPDATE-----------------------------
i remembered about this article that may fit your needs:
http://www.codeproject.com/KB/string/fastestcscaseinsstringrep.aspx