如何在 C# 中用一个空格替换字符串中的多个空格?
例子:
1 2 3 4 5
将会:
1 2 3 4 5
我喜欢使用:
myString = Regex.Replace(myString, @"\s+", " ");
因为它将捕获任何类型的空格(例如制表符、换行符等)并用单个空格替换它们。
string sentence = "This is a sentence with multiple spaces";
RegexOptions options = RegexOptions.None;
Regex regex = new Regex("[ ]{2,}", options);
sentence = regex.Replace(sentence, " ");
string xyz = "1 2 3 4 5";
xyz = string.Join( " ", xyz.Split( new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries ));
我认为马特的回答是最好的,但我不认为这是完全正确的。如果要替换换行符,则必须使用:
myString = Regex.Replace(myString, @"\s+", " ", RegexOptions.Multiline);
另一种使用 LINQ 的方法:
var list = str.Split(' ').Where(s => !string.IsNullOrWhiteSpace(s));
str = string.Join(" ", list);
它比所有这些都简单得多:
while(str.Contains(" ")) str = str.Replace(" ", " ");
Replace()
方法将处理给定字符串中所有出现的两个空格,因此我们不会为字符串中的每个配对空格实例循环(并重新分配整个字符串)。一个新的分配将处理所有这些。我们只在有 3 个或更多空格一起时才重新运行循环,这对于许多输入源来说可能很少发生。如果你能证明它对你的数据来说是一个问题,那么就去编写状态机,将一个字符一个字符地推送到一个新的字符串构建器中。
即使是简单的任务,正则表达式也会相当慢。这将创建一个可在任何 string
之外使用的扩展方法。
public static class StringExtension
{
public static String ReduceWhitespace(this String value)
{
var newString = new StringBuilder();
bool previousIsWhitespace = false;
for (int i = 0; i < value.Length; i++)
{
if (Char.IsWhiteSpace(value[i]))
{
if (previousIsWhitespace)
{
continue;
}
previousIsWhitespace = true;
}
else
{
previousIsWhitespace = false;
}
newString.Append(value[i]);
}
return newString.ToString();
}
}
它会这样使用:
string testValue = "This contains too much whitespace."
testValue = testValue.ReduceWhitespace();
// testValue = "This contains too much whitespace."
myString = Regex.Replace(myString, " {2,}", " ");
对于那些不喜欢 Regex
的人,这里有一个使用 StringBuilder
的方法:
public static string FilterWhiteSpaces(string input)
{
if (input == null)
return string.Empty;
StringBuilder stringBuilder = new StringBuilder(input.Length);
for (int i = 0; i < input.Length; i++)
{
char c = input[i];
if (i == 0 || c != ' ' || (c == ' ' && input[i - 1] != ' '))
stringBuilder.Append(c);
}
return stringBuilder.ToString();
}
在我的测试中,与静态编译的 Regex 相比,这种方法在处理大量中小型字符串时平均快 16 倍。与非编译或非静态正则表达式相比,这应该更快。
请记住,它不会删除前导或尾随空格,只会删除多次出现的空格。
这是一个较短的版本,仅当您只执行一次时才应使用它,因为每次调用它都会创建一个新的 Regex
类实例。
temp = new Regex(" {2,}").Replace(temp, " ");
如果你对正则表达式不太熟悉,这里有一个简短的解释:
{2,}
使正则表达式搜索其前面的字符,并查找 2 次到无限次之间的子字符串。
.Replace(temp, " ")
用空格替换字符串 temp 中的所有匹配项。
如果您想多次使用它,这里是一个更好的选择,因为它会在编译时创建正则表达式 IL:
Regex singleSpacify = new Regex(" {2,}", RegexOptions.Compiled);
temp = singleSpacify.Replace(temp, " ");
您可以在一个解决方案中简单地做到这一点!
string s = "welcome to london";
s.Replace(" ", "()").Replace(")(", "").Replace("()", " ");
如果您愿意,可以选择其他括号(甚至其他字符)。
"wel()come to london)("
变为 "wel come to london"
。您可以尝试使用大量括号。所以使用 ((((()))))
而不是 ()
和 )))))(((((
而不是 )(
。它仍然可以工作。不过,如果字符串包含 ((((()))))
或 )))))(((((
,这将失败。
没有 Regex,没有 Linq... 删除前导和尾随空格以及将任何嵌入的多个空格段减少到一个空格
string myString = " 0 1 2 3 4 5 ";
myString = string.Join(" ", myString.Split(new char[] { ' ' },
StringSplitOptions.RemoveEmptyEntries));
结果:“0 1 2 3 4 5”
// Mysample string
string str ="hi you are a demo";
//Split the words based on white sapce
var demo= str .Split(' ').Where(s => !string.IsNullOrWhiteSpace(s));
//Join the values back and add a single space in between
str = string.Join(" ", demo);
// output: string str ="hi you are a demo";
根据乔尔的说法,安慰其他答案,并希望随着我的进展略有改善:
您可以使用 Regex.Replace()
执行此操作:
string s = Regex.Replace (
" 1 2 4 5",
@"[ ]{2,}",
" "
);
或使用 String.Split()
:
static class StringExtensions
{
public static string Join(this IList<string> value, string separator)
{
return string.Join(separator, value.ToArray());
}
}
//...
string s = " 1 2 4 5".Split (
" ".ToCharArray(),
StringSplitOptions.RemoveEmptyEntries
).Join (" ");
我刚刚写了一个我喜欢的新 Join
,所以我想我会用它重新回答:
public static string Join<T>(this IEnumerable<T> source, string separator)
{
return string.Join(separator, source.Select(e => e.ToString()).ToArray());
}
一个很酷的事情是它可以通过在元素上调用 ToString() 来处理不是字符串的集合。用法还是一样的:
//...
string s = " 1 2 4 5".Split (
" ".ToCharArray(),
StringSplitOptions.RemoveEmptyEntries
).Join (" ");
许多答案都提供了正确的输出,但对于那些寻求最佳性能的人,我确实将 Nolanar's answer(这是性能的最佳答案)提高了大约 10%。
public static string MergeSpaces(this string str)
{
if (str == null)
{
return null;
}
else
{
StringBuilder stringBuilder = new StringBuilder(str.Length);
int i = 0;
foreach (char c in str)
{
if (c != ' ' || i == 0 || str[i - 1] != ' ')
stringBuilder.Append(c);
i++;
}
return stringBuilder.ToString();
}
}
使用正则表达式模式
[ ]+ #only space
var text = Regex.Replace(inputString, @"[ ]+", " ");
我知道这已经很老了,但是在尝试完成几乎相同的事情时遇到了这个问题。在 RegEx Buddy 中找到了这个解决方案。此模式将用单个空格替换所有双空格,并修剪前导和尾随空格。
pattern: (?m:^ +| +$|( ){2,})
replacement: $1
由于我们处理的是空白空间,因此有点难以阅读,所以这里再次将“空格”替换为“_”。
pattern: (?m:^_+|_+$|(_){2,}) <-- don't use this, just for illustration.
“(?m:” 构造启用了“多行”选项。我通常喜欢在模式本身中包含我可以使用的任何选项,以便它更加独立。
我可以用这个删除空格
while word.contains(" ") //double space
word = word.Replace(" "," "); //replace double space by single space.
word = word.trim(); //to remove single whitespces from start & end.
Trim()
您将删除所有删除前导和尾随 whitespace 字符,而不仅仅是空格。在用 Trim(' ')
修复它之后,问题就出现了,该问题从未要求删除前导和尾随(空白)空格。在通过完全删除 Trim(' ')
修复那个之后...您现在复制了 this old answer。另外,为什么要发布几乎是 C# 的代码,而这些代码只需稍作调整即可生效?
不使用正则表达式:
while (myString.IndexOf(" ", StringComparison.CurrentCulture) != -1)
{
myString = myString.Replace(" ", " ");
}
可以在短字符串上使用,但在有很多空格的长字符串上表现不佳。
试试这个方法
private string removeNestedWhitespaces(char[] st)
{
StringBuilder sb = new StringBuilder();
int indx = 0, length = st.Length;
while (indx < length)
{
sb.Append(st[indx]);
indx++;
while (indx < length && st[indx] == ' ')
indx++;
if(sb.Length > 1 && sb[0] != ' ')
sb.Append(' ');
}
return sb.ToString();
}
像这样使用它:
string test = removeNestedWhitespaces("1 2 3 4 5".toCharArray());
这是对 Nolonar original answer 的轻微修改。
检查字符是否不仅仅是一个空格,而是任何空格,使用这个:
它将用单个空格替换任何多个空格字符。
public static string FilterWhiteSpaces(string input)
{
if (input == null)
return string.Empty;
var stringBuilder = new StringBuilder(input.Length);
for (int i = 0; i < input.Length; i++)
{
char c = input[i];
if (i == 0 || !char.IsWhiteSpace(c) || (char.IsWhiteSpace(c) &&
!char.IsWhiteSpace(strValue[i - 1])))
stringBuilder.Append(c);
}
return stringBuilder.ToString();
}
strValue
应该是 input
。此外,IsWhiteSpace
包括换行符。您可能不想合并多个换行符,只要它会根据您的环境(\r\n
与 \n
)表现不同。在这种情况下,检查“CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.SpaceSeparator”。
去无赖怎么办?
public static string MinimizeWhiteSpace(
this string _this)
{
if (_this != null)
{
var returned = new StringBuilder();
var inWhiteSpace = false;
var length = _this.Length;
for (int i = 0; i < length; i++)
{
var character = _this[i];
if (char.IsWhiteSpace(character))
{
if (!inWhiteSpace)
{
inWhiteSpace = true;
returned.Append(' ');
}
}
else
{
inWhiteSpace = false;
returned.Append(character);
}
}
return returned.ToString();
}
else
{
return null;
}
}
混合使用 StringBuilder 和 Enumerable.Aggregate() 作为字符串的扩展方法:
using System;
using System.Linq;
using System.Text;
public static class StringExtension
{
public static string CondenseSpaces(this string s)
{
return s.Aggregate(new StringBuilder(), (acc, c) =>
{
if (c != ' ' || acc.Length == 0 || acc[acc.Length - 1] != ' ')
acc.Append(c);
return acc;
}).ToString();
}
public static void Main()
{
const string input = " (five leading spaces) (five internal spaces) (five trailing spaces) ";
Console.WriteLine(" Input: \"{0}\"", input);
Console.WriteLine("Output: \"{0}\"", StringExtension.CondenseSpaces(input));
}
}
执行此程序会产生以下输出:
Input: " (five leading spaces) (five internal spaces) (five trailing spaces) "
Output: " (five leading spaces) (five internal spaces) (five trailing spaces) "
Aggregate()
的一个很好、简短而直接的用法;但是,其中有一个错误。测试 acc.Length > 0
显然可以防止后面的 acc[acc.Length-1] != ' '
条件出现 IndexOutOfRange
异常,但这会防止发出 前导 空格字符,因为此时 acc
为空。我有 corrected this 到 acc.Length == 0 || acc[acc.Length - 1] != ' '
并且还扩展了示例代码以证明整个 s
中的单个和多个连续空格都得到了正确处理。
new StringBuilder(s.Length)
初始化 acc
,因为最长的结果 string
将是 - 当不进行替换时,因为 s
不包含连续空格字符 - 与输入的长度相同string
。另外,我建议使用像 CollapseSpaces()
或 CondenseSpaces()
这样的方法名称来更准确地描述它在做什么; “strip”听起来像是在删除 all 空格。
老派:
string oldText = " 1 2 3 4 5 ";
string newText = oldText
.Replace(" ", " " + (char)22 )
.Replace( (char)22 + " ", "" )
.Replace( (char)22 + "", "" );
Assert.That( newText, Is.EqualTo( " 1 2 3 4 5 " ) );
我查看了建议的解决方案,找不到可以处理我的情况可接受的空白字符混合的解决方案,例如:
Regex.Replace(input, @"\s+", " ") - 如果它们与空格混合,它将吃掉你的换行符,例如 \n \n 序列将被替换为
Regex.Replace(source, @"(\s)\s+", "$1") - 它取决于空格的第一个字符,这意味着它可能再次吃掉你的换行符
Regex.Replace(source, @"[ ]{2,}", " ") - 当混合了空白字符时,它将无法正常工作 - 例如 "\t \t "
可能并不完美,但对我来说快速的解决方案是:
Regex.Replace(input, @"\s+",
(match) => match.Value.IndexOf('\n') > -1 ? "\n" : " ", RegexOptions.Multiline)
想法是 - 换行符胜过空格和制表符。
这将无法正确处理 windows 换行符,但也很容易调整以使用它,不太了解正则表达式 - 可能适合单一模式。
以下代码将所有多个空格删除为单个空格
public string RemoveMultipleSpacesToSingle(string str)
{
string text = str;
do
{
//text = text.Replace(" ", " ");
text = Regex.Replace(text, @"\s+", " ");
} while (text.Contains(" "));
return text;
}
Regex.Replace()
第一次工作吗?此外,由于仅当字符连续 两次或多次 出现时才真正执行替换,因此您应该匹配:\s{2,}
。但是,最重要的是,这并没有按照方法名称的建议或这个问题的要求进行:\s
不仅匹配空格,还匹配 任何空格 字符。
您可以使用 RemoveDoubleSpaces() 之类的方法创建 StringsExtensions 文件。
StringsExtensions.cs
public static string RemoveDoubleSpaces(this string value)
{
Regex regex = new Regex("[ ]{2,}", RegexOptions.None);
value = regex.Replace(value, " ");
// this removes space at the end of the value (like "demo ")
// and space at the start of the value (like " hi")
value = value.Trim(' ');
return value;
}
然后你可以像这样使用它:
string stringInput =" hi here is a demo ";
string stringCleaned = stringInput.RemoveDoubleSpaces();
StartsWith
必须搜索整个字符串以获取 false
,如果字符串很大,则可能需要一些时间。第二和第三个循环是不必要的,第一个循环意味着最多可以有一个初始空间和最多一个最终空间。
Contains()
和 Replace()
都必须使用 IndexOf()
(或类似的东西)来定位指定的 string
,所以您所说的是“扫描指定的字符串以查看是否需要替换它,而这又需要再次进行扫描。”这类似于 if (dict.ContainsKey(key)) value = dict[key];
而不是 found = dict.TryGetValue(key, out value);
。如果一刀切(续)
*sWith()
调用所做的事情,可以将其替换为 value = value.TrimEnd(' ').TrimStart(' ');
,或者简单地说,value = value.Trim(' ');
,但无论如何,删除单独的前导或尾随空格与这个问题无关。如果不出意外,已经有几个答案使用了 string.Replace()
,而这个答案正在添加 nothing new。
" {2,}"
。我会回应@AdrianHHH 的评论,并说这个答案没有添加任何新的、有用的 信息,因此在一个已经包含太多信息的问题上显得杂乱无章。
不定期副业成功案例分享