有没有更好的方法来替换字符串?
我很惊讶Replace不接受字符数组或字符串数组。我想我可以写我自己的扩展,但我很好奇是否有更好的内置方式来做以下工作?注意最后一个Replace是一个字符串而不是字符。
myString.Replace(';', '\n').Replace(',', '\n').Replace('\r', '\n').Replace('\t', '\n').Replace(' ', '\n').Replace("\n\n", "\n");
有没有更好的方法来替换字符串?
我很惊讶Replace不接受字符数组或字符串数组。我想我可以写我自己的扩展,但我很好奇是否有更好的内置方式来做以下工作?注意最后一个Replace是一个字符串而不是字符。
myString.Replace(';', '\n').Replace(',', '\n').Replace('\r', '\n').Replace('\t', '\n').Replace(' ', '\n').Replace("\n\n", "\n");
当前回答
就性能而言,这可能不是最好的解决方案,但它确实有效。
var str = "filename:with&bad$separators.txt";
char[] charArray = new char[] { '#', '%', '&', '{', '}', '\\', '<', '>', '*', '?', '/', ' ', '$', '!', '\'', '"', ':', '@' };
foreach (var singleChar in charArray)
{
str = str.Replace(singleChar, '_');
}
其他回答
没有“替换”(仅限Linq):
string myString = ";,\r\t \n\n=1;;2,,3\r\r4\t\t5 6\n\n\n\n7=";
char NoRepeat = '\n';
string ByeBye = ";,\r\t ";
string myResult = myString.ToCharArray().Where(t => !"STOP-OUTSIDER".Contains(t))
.Select(t => "" + ( ByeBye.Contains(t) ? '\n' : t))
.Aggregate((all, next) => (
next == "" + NoRepeat && all.Substring(all.Length - 1) == "" + NoRepeat
? all : all + next ) );
使用正则表达式。替换,像这样:
string input = "This is text with far too much " +
"whitespace.";
string pattern = "[;,]";
string replacement = "\n";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(input, replacement);
这里是关于RegEx的MSDN文档的更多信息。取代
一个. net Core版本,用于将一组已定义的字符串字符替换为特定的字符。它利用了最近引入的Span类型和字符串。创建方法。
其思想是准备一个替换数组,因此不需要对每个字符串字符进行实际的比较操作。因此,替换过程提醒状态机的工作方式。为了避免初始化替换数组的所有项,让我们将oldChar ^ newChar (XOR'ed)值存储在那里,这样做有以下好处:
如果一个字符是不变的:ch ^ ch = 0 -不需要初始化不变的项 最后一个char可以通过XOR'ing: ch ^ repl[ch]: Ch ^ 0 = Ch -不变字符大小写 ch ^ (ch ^ newChar) = newChar -替换的char
因此,唯一的要求是确保替换数组在初始化时为零。我们将使用ArrayPool<char>来避免每次调用ReplaceAll方法时进行分配。并且,为了确保数组为零而不需要调用Array。方法,我们将维护一个专门用于ReplaceAll方法的池。在将替换数组返回到池之前,我们将清除替换数组(仅是精确的项)。
public static class StringExtensions
{
private static readonly ArrayPool<char> _replacementPool = ArrayPool<char>.Create();
public static string ReplaceAll(this string str, char newChar, params char[] oldChars)
{
// If nothing to do, return the original string.
if (string.IsNullOrEmpty(str) ||
oldChars is null ||
oldChars.Length == 0)
{
return str;
}
// If only one character needs to be replaced,
// use the more efficient `string.Replace`.
if (oldChars.Length == 1)
{
return str.Replace(oldChars[0], newChar);
}
// Get a replacement array from the pool.
var replacements = _replacementPool.Rent(char.MaxValue + 1);
try
{
// Intialize the replacement array in the way that
// all elements represent `oldChar ^ newChar`.
foreach (var oldCh in oldChars)
{
replacements[oldCh] = (char)(newChar ^ oldCh);
}
// Create a string with replaced characters.
return string.Create(str.Length, (str, replacements), (dst, args) =>
{
var repl = args.replacements;
foreach (var ch in args.str)
{
dst[0] = (char)(repl[ch] ^ ch);
dst = dst.Slice(1);
}
});
}
finally
{
// Clear the replacement array.
foreach (var oldCh in oldChars)
{
replacements[oldCh] = char.MinValue;
}
// Return the replacement array back to the pool.
_replacementPool.Return(replacements);
}
}
}
我知道这个问题非常古老,但我想提供两个更有效的选择:
首先,Paul Walls发布的扩展方法很好,但可以通过使用StringBuilder类来提高效率,StringBuilder类类似于字符串数据类型,但专门用于需要多次更改字符串值的情况。下面是我用StringBuilder做的扩展方法的一个版本:
public static string ReplaceChars(this string s, char[] separators, char newVal)
{
StringBuilder sb = new StringBuilder(s);
foreach (var c in separators) { sb.Replace(c, newVal); }
return sb.ToString();
}
我运行了这个操作10万次,使用StringBuilder花费了73毫秒,而使用string花费了81毫秒。所以区别通常是可以忽略不计的,除非你运行很多操作或使用一个巨大的字符串。
其次,这里有一个你可以使用的1线循环:
foreach (char c in separators) { s = s.Replace(c, '\n'); }
我个人认为这是最好的选择。它非常高效,并且不需要编写扩展方法。在我的测试中,这种方法在63毫秒内运行了10万次迭代,是最高效的。 下面是一个上下文中的例子:
string s = "this;is,\ra\t\n\n\ntest";
char[] separators = new char[] { ' ', ';', ',', '\r', '\t', '\n' };
foreach (char c in separators) { s = s.Replace(c, '\n'); }
本例的前两行要归功于Paul Walls。
这是最短的方法:
myString = Regex.Replace(myString, @"[;,\t\r ]|[\n]{2}", "\n");