zoukankan      html  css  js  c++  java
  • 如何去掉字符串中的空格(转)

    1. 写在前面的

    事情的起因是这样的,我要处理一段这样的程序,用户可以以任意的形式输入11位数字+空格的形式,然后我要把他分成434的格式。

    然后想到的办法是: 去掉所有空格,然后按照规则划分成数组,然后再输出。

    那么怎么样去掉空格,常规的方法这么几个:

    A. String.Replace()

    B. String.Split(new char[]{‘ ’},StringSplitOptions.RemoveEmptyEntries);

    C. System.Text.Regex()来进行正则替换

    D. 有人提出用StringBuilder,但是我们永远不要忘记StringBuilder的临界值,在小数据的情况下,使用StringBuilder反而是得不偿失的。

    2. 性能大比拼

    毋容置疑,使用正则一定是最慢的办法,再次不做演示。

    首先贴出测试代码:

    static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            string sTemp = "11  1241    111  11 ";
            string sTest = String.Empty;
            for (int i = 0; i < 1000; i++)
            {
                sTest += sTemp;
            }
            sw.Start();
            for (int i = 0; i < 1000; i++)
            {
                sTest.Replace(" ", "");
            }
            sw.Stop();
            Console.Write("使用Replace所消耗的时间:");
            Console.WriteLine(sw.ElapsedMilliseconds.ToString());
            sw.Reset();
            sw.Start();
            for (int i = 0; i < 1000; i++)
            {
                sTest.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            }
            sw.Stop();
            Console.Write("使用Split所消耗的时间:");
            Console.WriteLine(sw.ElapsedMilliseconds.ToString());
        }

    接下来是测试结果:

    image

    正如我们意料中的一样,Replace的效率一定要比Split高的,猜测的理由其实很简单,Replace的作用就是用来替换字符,而Split是用来拆分,这里属于典型的方法乱用。

    扩展阅读: 《.NET,你忘记了么?(八)—— 从dynamic到特性误用》

    3. 谈谈String.Split()

    我没有办法看到String.Replace()源码,那么在这里就只说说String.Split()。

    大致代码可以通过Reflector看到,这里只粘贴出核心的代码:

    public string[] Split(string[] separator, int count, StringSplitOptions options)
    {
        bool flag = options == StringSplitOptions.RemoveEmptyEntries;
        int[] sepList = new int[this.Length];
        int[] lengthList = new int[this.Length];
        int numReplaces = this.MakeSeparatorList(separator, ref sepList, ref lengthList);
        if ((numReplaces == 0) || (count == 1))
        {
            return new string[] { this };
        }
        if (flag)
        {
            return this.InternalSplitOmitEmptyEntries(sepList, lengthList, numReplaces, count);
        }
        return this.InternalSplitKeepEmptyEntries(sepList, lengthList, numReplaces, count);
    }

    首先我们来关注下MakeSeparatorList方法,在这个方法里,微软通过遍历分隔符数组和字符串,两层for循环,得到了字符串中,每个分隔符所在的索引。接下来就是根据索引来直接分割字符串了,无需赘言。

    4. 算法分析

    从上面的代码,我们可以很轻松地看出,算法的时间复杂度是O(M*N),那么我们有没有更优的算法来实现他呢?

    首先,我们要看到算法的时间复杂度瓶颈在于MakeSeparatorList方法,那就来优化这个方法,实现如下:

    private static bool[] MakeSeparatorList(char[] separatorArray)
    {
        bool[] charArray = new bool[255];
        for (int i = 0; i < separatorArray.Length; i++)
        {
            charArray[separatorArray[i]] = true;
        }
        return charArray;
    }

    那么之后我们就可以在遍历字符串的时候,直接通过每个字符的ASC2码来得到这个字符是否是分隔符了。

    5. 算法优劣

    既然这样的算法时间复杂度小,那为什么微软不采用这样的算法呢?

    时间复杂度并不能决定算法的优劣,我们所谓的指数型,对数型还是ON级,都是针对当数据量大幅度增长时。但是在此问题中,分隔符只有1个,我们却需要为这一个字符去声明一个大小为255的bool型数组,这在空间复杂度上是很得不偿失的。

    那么该算法适合什么?该算法适合当分隔符具有多个,字符串也很长时,那么O(N)就远远小于O(M*N)了。

    6. 写在最后

    好久没有写东西了,以至于写写自己已经不知道自己在写什么了。

    东西写得乱七八糟,算了算了…….

    只是警醒自己,也警醒各位,.NET Framework为我们提供了大量的类库方法支持,但是在用一个方法之前,我们是否该把这个方法搞清楚,这个方法是否是最优的方法,我们是该自己重新写一个方法,还是……

    追本溯源,这才是程序员该做的。

    原文:http://www.cnblogs.com/kym/archive/2009/12/07/1618293.html

  • 相关阅读:
    mysql复制那点事
    全排列问题
    56. Merge Interval
    2. Add Two Numbers
    20. Valid Parentheses
    121. Best Time to Buy and Sell Stock
    120. Triangle
    96. Unique Binary Search Trees
    91. Decode Ways
    72. Edit Distance
  • 原文地址:https://www.cnblogs.com/zgblog/p/2498036.html
Copyright © 2011-2022 走看看