C# 替换单个空格而不替换多个空格
我有一个字符串,格式如下:C# 替换单个空格而不替换多个空格,c#,whitespace,C#,Whitespace,我有一个字符串,格式如下: abc def ghi xyz 我想以以下格式结束: abcdefghi xyz 最好的方法是什么?在这种特殊情况下,我可以删去最后三个字符,删除空格,然后在结尾添加它们,但是对于多个空间位于字符串中间的情况,这将不起作用。 简而言之,我想删除所有单个空格,然后用单个空格替换所有多个空格。这些步骤中的每一步本身都很简单,但将它们结合起来似乎不那么简单 我愿意使用正则表达式,但我不想使用。好吧,正则表达式可能是这里最快的,但您可以实现一些算法,对单个空间使用前瞻,然后在
abc def ghi xyz
我想以以下格式结束:
abcdefghi xyz
最好的方法是什么?在这种特殊情况下,我可以删去最后三个字符,删除空格,然后在结尾添加它们,但是对于多个空间位于字符串中间的情况,这将不起作用。
简而言之,我想删除所有单个空格,然后用单个空格替换所有多个空格。这些步骤中的每一步本身都很简单,但将它们结合起来似乎不那么简单
我愿意使用正则表达式,但我不想使用。好吧,正则表达式可能是这里最快的,但您可以实现一些算法,对单个空间使用前瞻,然后在循环中替换多个空间:
// Replace all single whitespaces
for (int i = 0; i < sourceString.Length; i++)
{
if (sourceString[i] = ' ')
{
if (i < sourceString.Length - 1 && sourceString[i+1] != ' ')
sourceString = sourceString.Delete(i);
}
}
// Replace multiple whitespaces
while (sourceString.Contains(" ")) // Two spaces here!
sourceString = sourceString.Replace(" ", " ");
//替换所有单个空格
for(int i=0;i
但是,与适当的正则表达式相比,这段代码非常难看而且速度很慢…这种方法使用正则表达式,但希望在某种程度上仍然具有相当的可读性。首先,在多个空格上拆分输入字符串
var pattern = @" +"; // match two or more spaces
var groups = Regex.Split(input, pattern);
接下来,从每个令牌中删除(单个)空格:
var tokens = groups.Select(group => group.Replace(" ", String.Empty));
最后,用单个空格连接您的令牌
var result = String.Join(' ', tokens.ToArray());
此示例使用文本空格字符而不是“空格”(包括制表符、换行符等)-如果需要拆分多个空格字符而不是实际空格,请用“
\s
替换为”。对于非正则表达式选项,可以使用:
string str = "abc def ghi xyz";
var result = str.Split(); //This will remove single spaces from the result
StringBuilder sb = new StringBuilder();
bool ifMultipleSpacesFound = false;
for (int i = 0; i < result.Length;i++)
{
if (!String.IsNullOrWhiteSpace(result[i]))
{
sb.Append(result[i]);
ifMultipleSpacesFound = false;
}
else
{
if (!ifMultipleSpacesFound)
{
ifMultipleSpacesFound = true;
sb.Append(" ");
}
}
}
string output = sb.ToString();
这里有一种方法使用了一些相当微妙的逻辑:
public static string RemoveUnwantedSpaces(string text)
{
var sb = new StringBuilder();
char lhs = '\0';
char mid = '\0';
foreach (char rhs in text)
{
if (rhs != ' ' || (mid == ' ' && lhs != ' '))
sb.Append(rhs);
lhs = mid;
mid = rhs;
}
return sb.ToString().Trim();
}
工作原理:
var tmp = Regex.Replace("abc def ghi xyz", "( )([^ ])", "$2")
我们将在字符串中线性地检查每个可能的三字符子序列(在一种三字符滑动窗口中)。这三个字符将依次由变量lhs
、mid
和rhs
表示
对于字符串中的每个rhs
字符:
- 如果它不是一个空间,我们应该输出它李>
- 如果它是一个空格,前一个字符也是空格,但前一个字符不是,那么这是至少两个空格序列中的第二个,因此我们应该输出一个空格
- 否则,不要输出空间,因为这是两个或更多空间序列中的第一个或第三个(或更晚)空间,并且在任何情况下我们都不想输出空间:如果这恰好是两个或更多空间序列中的第一个,则在出现第二个空间时将输出一个空间。如果这是第三个或更高版本,我们已经为它输出了一个空间
这里的微妙之处在于,我通过使用非空格字符初始化
lhs
和mid
变量,避免了序列开头的特殊大小写。这些值是什么并不重要,只要它们不是空格,但我将它们设置为\0
,以表明它们是特殊值。经过仔细考虑,这里有一行:
这样做的结果是“abcdefghi xyz”
原始答案:
var tmp = Regex.Replace("abc def ghi xyz", "( )([^ ])", "$2")
两行代码正则表达式解决方案:
var tmp = Regex.Replace("abc def ghi xyz", "( )([^ ])", "$2")
tmp
是“abcdefghi xyz”
然后:
结果
是“abcdefghi xyz”
说明:
var tmp = Regex.Replace("abc def ghi xyz", "( )([^ ])", "$2")
第一行代码删除单个空格,并为多个空格删除一个空格(因此tmp
中字母i和x之间有3个空格)
第二行只是用一个空格替换多个空格
第一行的深入解释:
var tmp = Regex.Replace("abc def ghi xyz", "( )([^ ])", "$2")
我们将输入字符串与正则表达式匹配,正则表达式匹配一个空格和它旁边的非空格。我们还将这两个字符分为不同的组(我们使用(
)
进行匿名分组)。
因此,对于“abc def ghi xyz”
字符串,我们有以下匹配项和组:
匹配:“d”
group1:“”
group2:“d”
匹配:“g”
group1:“”
group2:“g”
匹配:“x”
group1:“”
group2:“x”
我们正在使用for
Regex。Replace
方法将匹配替换为第二组的内容(非空白字符)使用Regex将是您最好的选择。看起来这里已经回答了这个问题:多个空格似乎没有正确显示。第一个字符串示例在“ghi”和“xyz”之间有几个空格,而不是实际的文本(多个空格)。@Michael B:这个问题不是一回事。这很聪明。我有一部分人非常欣赏这个解决方案,但另一个不想让它靠近我的代码库。@aaron其实没那么复杂。我已经重命名了循环变量,以便更清楚地了解发生了什么。默认的string.split()实际上会删除所有的空格,所以我认为这不管用。@aaron,它只会删除一个空格,不会删除多个空格。我已经测试了这个代码,然后才把它放在答案中。你说得对。我也尝试过类似的方法,但有一两个逻辑错误使我无法得到正确的结果。