我正在调用一个REST API,并收到一个XML响应。它返回一个工作区名称列表,我正在编写一个快速的IsExistingWorkspace()方法。因为所有的工作空间都是由没有空格的连续字符组成的,我假设找出特定工作空间是否在列表中最简单的方法是删除所有空格(包括换行符)并这样做(XML是从web请求接收到的字符串):

XML.Contains("<name>" + workspaceName + "</name>");

我知道这是区分大小写的,我就靠这一点了。我只是需要一种方法来有效地删除字符串中的所有空白。我知道RegEx和LINQ可以做到,但我对其他想法持开放态度。我最关心的是速度。


当前回答

Regex太夸张了;只是在字符串上使用扩展(感谢Henk)。这是微不足道的,应该是框架的一部分。总之,这是我的实现:

public static partial class Extension
{
    public static string RemoveWhiteSpace(this string self)
    {
        return new string(self.Where(c => !Char.IsWhiteSpace(c)).ToArray());
    }
}

其他回答

Regex太夸张了;只是在字符串上使用扩展(感谢Henk)。这是微不足道的,应该是框架的一部分。总之,这是我的实现:

public static partial class Extension
{
    public static string RemoveWhiteSpace(this string self)
    {
        return new string(self.Where(c => !Char.IsWhiteSpace(c)).ToArray());
    }
}

这是我所知道的最快的方法,即使你说你不想使用正则表达式:

Regex.Replace(XML, @"\s+", "");

如果您计划多次这样做,请在评论中注明@ hyperhuman,创建并存储一个Regex实例。这将节省每次构建它的开销,这比您想象的要昂贵得多。

private static readonly Regex sWhitespace = new Regex(@"\s+");
public static string ReplaceWhitespace(string input, string replacement) 
{
    return sWhitespace.Replace(input, replacement);
}

下面是RegEx解决方案的一个简单的线性替代方案。我不知道哪个更快;你必须对它进行基准测试。

static string RemoveWhitespace(string input)
{
    StringBuilder output = new StringBuilder(input.Length);

    for (int index = 0; index < input.Length; index++)
    {
        if (!Char.IsWhiteSpace(input, index))
        {
            output.Append(input[index]);
        }
    }
    return output.ToString();
}

这是另一种变体:

public static string RemoveAllWhitespace(string aString)
{
  return String.Join(String.Empty, aString.Where(aChar => aChar !Char.IsWhiteSpace(aChar)));
}

与大多数其他解决方案一样,我没有执行详尽的基准测试,但这对于我的目的来说已经足够好了。

我在CodeProject上找到了一篇由Felipe Machado(在Richard Robertson的帮助下)撰写的关于这方面的不错的文章。

他测试了十种不同的方法。这是最快安全的版本…

public static string TrimAllWithInplaceCharArray(string str) {

    var len = str.Length;
    var src = str.ToCharArray();
    int dstIdx = 0;

    for (int i = 0; i < len; i++) {
        var ch = src[i];

        switch (ch) {

            case '\u0020': case '\u00A0': case '\u1680': case '\u2000': case '\u2001':

            case '\u2002': case '\u2003': case '\u2004': case '\u2005': case '\u2006':

            case '\u2007': case '\u2008': case '\u2009': case '\u200A': case '\u202F':

            case '\u205F': case '\u3000': case '\u2028': case '\u2029': case '\u0009':

            case '\u000A': case '\u000B': case '\u000C': case '\u000D': case '\u0085':
                continue;

            default:
                src[dstIdx++] = ch;
                break;
        }
    }
    return new string(src, 0, dstIdx);
}

最快的不安全版本…(Sunsetquest 2021年5月26日的一些改进)

public static unsafe void RemoveAllWhitespace(ref string str)
{
    fixed (char* pfixed = str)
    {
        char* dst = pfixed;
        for (char* p = pfixed; *p != 0; p++)
        {
            switch (*p)
            {
                case '\u0020': case '\u00A0': case '\u1680': case '\u2000': case '\u2001':
                case '\u2002': case '\u2003': case '\u2004': case '\u2005': case '\u2006':
                case '\u2007': case '\u2008': case '\u2009': case '\u200A': case '\u202F':
                case '\u205F': case '\u3000': case '\u2028': case '\u2029': case '\u0009':
                case '\u000A': case '\u000B': case '\u000C': case '\u000D': case '\u0085':
                continue;

                default:
                    *dst++ = *p;
                    break;
            }
        }

        uint* pi = (uint*)pfixed;
        ulong len = ((ulong)dst - (ulong)pfixed) >> 1;
        pi[-1] = (uint)len;
        pfixed[len] = '\0';
    }
}

在Stack Overflow上也有一些由Stian Standahl编写的独立基准测试,它们也显示了Felipe的函数比第二快的函数快300%。另外,对于我修改的那个,我使用了这个技巧。