【问题标题】:Replace Single WhiteSpace without Replacing Multiple WhiteSpace替换单个空格而不替换多个空格
【发布时间】:2017-09-21 18:22:12
【问题描述】:

我有一个格式为: abc def ghi xyz

我想以以下格式结束: abcdefghi xyz

最好的方法是什么?在这种特殊情况下,我可以去掉最后三个字符,删除空格,然后在末尾添加它们,但这不适用于多个空格位于字符串中间的情况。

简而言之,我想删除所有单个空格,然后用单个空格替换所有多个空格。这些步骤中的每一个本身都很简单,但是将它们组合起来似乎不太简单。

我愿意使用正则表达式,但我不愿意。

【问题讨论】:

  • 使用 RegEx 将是您最好的选择。看起来这已经在这里得到了回答:stackoverflow.com/questions/1279859/…
  • Multiple Whitespaces don' 似乎无法正确显示。第一个字符串示例在“ghi”和“xyz”之间有几个空格,而不是实际的文本“(多个空格)”。
  • @Michael B:这个问题不太一样。

标签: c# whitespace


【解决方案1】:

这种方法使用正则表达式,但希望以一种仍然相当可读的方式。首先,将输入字符串拆分为多个空格

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 代替“”。

【讨论】:

  • 这很聪明。
【解决方案2】:

嗯,正则表达式在这里可能是最快的,但您可以实现一些算法,对单个空格使用前瞻,然后在循环中替换多个空格:

// 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("  ", " ");

但是,与正确的正则表达式相比,该代码非常丑陋和缓慢......

【讨论】:

    【解决方案3】:

    对于非 REGEX 选项,您可以使用:

    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();
    

    输出将是:

    output = "abcdefghi xyz"
    

    【讨论】:

    • 默认的 string.split() 实际上会删除所有的空格,所以我认为这行不通。
    • @aaron,它只会删除一个空格,而不是多个空格。在将其放入答案之前,我已经测试了此代码
    • 嗯。你是对的。我曾尝试过类似的方法,但有一两个逻辑错误使我无法获得正确的结果。
    【解决方案4】:

    这是一种使用一些相当微妙的逻辑的方法:

    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();
    }
    

    工作原理:

    我们将在字符串中线性检查每个可能的三字符子序列(在一种三字符滑动窗口中)。这三个字符将依次由变量lhsmidrhs 表示。

    对于字符串中的每个rhs 字符:

    • 如果不是空格,我们应该输出它。
    • 如果它一个空格,并且前一个字符也是空格,但前一个不是,那么这是至少一个序列中的第二个两个空格,因此我们应该输出一个空格。
    • 否则,不要输出空格,因为这是两个或多个空格序列中的第一个或第三个(或以后)空格,并且在任何一种情况下,我们都不想输出空格:如果发生这种情况要成为两个或多个空格序列中的第一个,当第二个空格出现时将输出一个空格。如果这是第三个或更晚,我们已经为它输出了一个空格。

    这里的微妙之处在于,我通过使用非空格字符初始化 lhsmid 变量来避免在序列的开头使用特殊大小写。这些值是什么无关紧要,只要它们不是空格,但我将它们设为\0 以表明它们是特殊值。

    【讨论】:

    • 我的一部分人非常欣赏这个解决方案,但另一部分人不希望它靠近我的代码存储库。
    • @aaron 其实没那么复杂。我重命名了循环变量,以便更清楚地了解发生了什么。
    【解决方案5】:

    三思而后行是一行regex solution:

    Regex.Replace("abc def ghi    xyz", "( )( )*([^ ])", "$2$3")
    

    这个结果是"abcdefghi xyz"

    原始答案:

    两行代码正则解决方案:

    var tmp = Regex.Replace("abc def ghi    xyz", "( )([^ ])", "$2")
    

    tmp"abcdefghi xyz" 那么:

    var result = Regex.Replace(tmp, "( )+", " ");
    

    result"abcdefghi xyz"


    说明:

    第一行代码去掉单个空格,去掉一个空格对应多个空格(所以tmp中字母ix之间有3个空格)。

    第二行只是用一个替换多个空格。

    深入解释第一行:

    我们将输入字符串匹配到匹配一个空格和非空格的正则表达式。我们还将这两个字符放在不同的组中(我们使用() 进行匿名分组)。 所以对于"abc def ghi xyz" 字符串,我们有这个匹配和组:

    匹配:" d" group1:" " group2:"d"

    匹配:" g" group1:" " group2:"g"

    匹配:" x" group1:" " group2:"x"

    我们正在使用substitution syntax for Regex.Replace 方法将匹配替换为第二组的内容(非空白字符)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-21
      • 1970-01-01
      • 2010-11-19
      • 1970-01-01
      相关资源
      最近更新 更多