如何在没有特定事件的情况下替换特定字符串
How to replace certain string without certain occurrence
例如此处的文本:
text = "Chapter 44. 7h3 v3nd3774"
我想要这样输出
outcome = "Chapter 44. The colosseum"
如果我只是使用这样的方法:
string s = text.Replace("4", "a").Replace("3", "e").Replace("6", "g").Replace("1", "I").Replace("0", "o").Replace("5", "s").Replace("7", "t");
System.Console.WriteLine("Contents of WriteText.txt = {0}", s);
会输出为Chapter aa. the vendetta
,正确的部分也变了,不知道有没有简单的解决办法?
如果您可以表达用于确定哪些数字应该转换的逻辑规则,那么是的,那应该不会太难。
从您的示例来看,您似乎只想将数字更改为与字母直接相邻的字母。如果这是唯一的规则,那么您可以这样做:
public static string Translate(string input)
{
if (string.IsNullOrEmpty(input)) return input;
var charMap = new Dictionary<char, char>
{
{'4', 'a'}, {'3', 'e'}, {'6', 'g'}, {'1', 'i'},
{'0', 'o'}, {'5', 's'}, {'7', 't'}
};
var suffixes = new List<string>
{
"st", "nd", "rd", "th"
};
var result = new StringBuilder();
for (var i = 0; i < input.Length; i++)
{
// If the previous or next character is a letter and this character
// is in the mapping dictionary, replace it with the mapped character
if (((i > 0 && char.IsLetter(result[i - 1])) ||
(i < input.Length - 1 && char.IsLetter(input[i + 1]))) &&
charMap.ContainsKey(input[i]) &&
(i == input.Length - 1 || !IsValidSuffix(input.Substring(i + 1), suffixes)))
{
result.Append(charMap[input[i]]);
// Because we're changing characters from left to right and we just
// changed this character to a letter, we need to walk backwards and
// check the previous characters since they may now need to change.
// For example the 51 in '517u4710n' would not change without this check
var prevIndex = i - 1;
while (prevIndex >= 0 && charMap.ContainsKey(result[prevIndex]))
{
result[prevIndex] = charMap[result[prevIndex]];
prevIndex--;
}
}
else
{
result.Append(input[i]);
}
}
return result.ToString();
}
// Helper method to determine if a number is followed by a "valid suffix",
// which is used to prevent converting numbers when they should remain
// numbers; such as "24th", where we don't want to change the '4' to an 'a'.
public static bool IsValidSuffix(string input, List<string> validSuffixes)
{
if (input == null) return validSuffixes == null;
if (input == string.Empty) return true;
if ((validSuffixes?.Count).GetValueOrDefault() == 0) return false;
var match = validSuffixes
.OrderByDescending(s => s.Length)
.FirstOrDefault(input.StartsWith);
return match != null &&
(input.Length == match.Length ||
!char.IsLetter(input[match.Length]));
}
// Output: Translate("Chapter 44. 7h3 v3nd3774") == "Chapter 44. the vendetta"
如果您的逻辑是将整数保留为 'correct' 部分,您可以尝试在应用替换逻辑后找到这些数字并将它们放回 'corrected' 句子中。
此外,当您多次更改字符串时,我建议使用 StringBuilder 来解决性能问题。
这里是一个代码建议:
`
void Main()
{
var text = "Chapter 44. 7h3 v3nd3774";
var outcome = RemoveLeet(text);
Console.WriteLine(outcome);
}
bool IsDigit(char c)
{
return c >= '0' && c <= '9';
}
bool IsLetter(char c)
{
return c >= 'a' && c <= 'z' || c >= 'A' && c >= 'Z';
}
string RemoveLeet(string text)
{
var sb = new StringBuilder(text);
sb
.Replace("4", "a").Replace("3", "e").Replace("6", "g").Replace("1", "I")
.Replace("0", "o").Replace("5", "s").Replace("7", "t");
var outcome = sb.ToString();
for (int i = 0; i < text.Length;)
{
if (IsDigit(text[i++]))
{
int numberLength = 1;
for (;i < text.Length; i++)
{
if (!IsDigit(text[i]))
break;
numberLength += 1;
}
var indexBeforeNumber = i - numberLength - 1;
//check number did not start inside a word
if (indexBeforeNumber < 0 || !IsLetter(text[indexBeforeNumber]))
{
//check number is not followed by a word
if (i == text.Length || !IsLetter(text[i]))
{
var number = text.Substring(i - numberLength, numberLength);
var outcomeBegin = indexBeforeNumber < 1 ? "" : outcome.Substring(0, indexBeforeNumber + 1);
var outcomeAfter = i == text.Length ? "" : outcome.Substring(i, text.Length - i);
outcome = $"{outcomeBegin}{number}{outcomeAfter}";
}
}
}
}
return outcome;
}
`
例如此处的文本:
text = "Chapter 44. 7h3 v3nd3774"
我想要这样输出
outcome = "Chapter 44. The colosseum"
如果我只是使用这样的方法:
string s = text.Replace("4", "a").Replace("3", "e").Replace("6", "g").Replace("1", "I").Replace("0", "o").Replace("5", "s").Replace("7", "t");
System.Console.WriteLine("Contents of WriteText.txt = {0}", s);
会输出为Chapter aa. the vendetta
,正确的部分也变了,不知道有没有简单的解决办法?
如果您可以表达用于确定哪些数字应该转换的逻辑规则,那么是的,那应该不会太难。
从您的示例来看,您似乎只想将数字更改为与字母直接相邻的字母。如果这是唯一的规则,那么您可以这样做:
public static string Translate(string input)
{
if (string.IsNullOrEmpty(input)) return input;
var charMap = new Dictionary<char, char>
{
{'4', 'a'}, {'3', 'e'}, {'6', 'g'}, {'1', 'i'},
{'0', 'o'}, {'5', 's'}, {'7', 't'}
};
var suffixes = new List<string>
{
"st", "nd", "rd", "th"
};
var result = new StringBuilder();
for (var i = 0; i < input.Length; i++)
{
// If the previous or next character is a letter and this character
// is in the mapping dictionary, replace it with the mapped character
if (((i > 0 && char.IsLetter(result[i - 1])) ||
(i < input.Length - 1 && char.IsLetter(input[i + 1]))) &&
charMap.ContainsKey(input[i]) &&
(i == input.Length - 1 || !IsValidSuffix(input.Substring(i + 1), suffixes)))
{
result.Append(charMap[input[i]]);
// Because we're changing characters from left to right and we just
// changed this character to a letter, we need to walk backwards and
// check the previous characters since they may now need to change.
// For example the 51 in '517u4710n' would not change without this check
var prevIndex = i - 1;
while (prevIndex >= 0 && charMap.ContainsKey(result[prevIndex]))
{
result[prevIndex] = charMap[result[prevIndex]];
prevIndex--;
}
}
else
{
result.Append(input[i]);
}
}
return result.ToString();
}
// Helper method to determine if a number is followed by a "valid suffix",
// which is used to prevent converting numbers when they should remain
// numbers; such as "24th", where we don't want to change the '4' to an 'a'.
public static bool IsValidSuffix(string input, List<string> validSuffixes)
{
if (input == null) return validSuffixes == null;
if (input == string.Empty) return true;
if ((validSuffixes?.Count).GetValueOrDefault() == 0) return false;
var match = validSuffixes
.OrderByDescending(s => s.Length)
.FirstOrDefault(input.StartsWith);
return match != null &&
(input.Length == match.Length ||
!char.IsLetter(input[match.Length]));
}
// Output: Translate("Chapter 44. 7h3 v3nd3774") == "Chapter 44. the vendetta"
如果您的逻辑是将整数保留为 'correct' 部分,您可以尝试在应用替换逻辑后找到这些数字并将它们放回 'corrected' 句子中。 此外,当您多次更改字符串时,我建议使用 StringBuilder 来解决性能问题。
这里是一个代码建议: `
void Main()
{
var text = "Chapter 44. 7h3 v3nd3774";
var outcome = RemoveLeet(text);
Console.WriteLine(outcome);
}
bool IsDigit(char c)
{
return c >= '0' && c <= '9';
}
bool IsLetter(char c)
{
return c >= 'a' && c <= 'z' || c >= 'A' && c >= 'Z';
}
string RemoveLeet(string text)
{
var sb = new StringBuilder(text);
sb
.Replace("4", "a").Replace("3", "e").Replace("6", "g").Replace("1", "I")
.Replace("0", "o").Replace("5", "s").Replace("7", "t");
var outcome = sb.ToString();
for (int i = 0; i < text.Length;)
{
if (IsDigit(text[i++]))
{
int numberLength = 1;
for (;i < text.Length; i++)
{
if (!IsDigit(text[i]))
break;
numberLength += 1;
}
var indexBeforeNumber = i - numberLength - 1;
//check number did not start inside a word
if (indexBeforeNumber < 0 || !IsLetter(text[indexBeforeNumber]))
{
//check number is not followed by a word
if (i == text.Length || !IsLetter(text[i]))
{
var number = text.Substring(i - numberLength, numberLength);
var outcomeBegin = indexBeforeNumber < 1 ? "" : outcome.Substring(0, indexBeforeNumber + 1);
var outcomeAfter = i == text.Length ? "" : outcome.Substring(i, text.Length - i);
outcome = $"{outcomeBegin}{number}{outcomeAfter}";
}
}
}
}
return outcome;
}
`