【问题标题】:How can I speed up this method which removes text from a string?如何加快这种从字符串中删除文本的方法?
【发布时间】:2010-01-15 13:58:56
【问题描述】:

我编写了以下方法从字符串中删除括号中的命名空间。

我想让它尽可能

有没有办法加快下面的代码?

using System;

namespace TestRemoveFast
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] tests = {
            "{http://company.com/Services/Types}ModifiedAt",
            "{http://company.com/Services/Types}CreatedAt"
                             };

            foreach (var test in tests)
            {
                Console.WriteLine(Clean(test));
            }

            Console.ReadLine();
        }

        static string Clean(string line)
        {
            int pos = line.IndexOf('}');
            if (pos > 0)
                return line.Substring(pos + 1, line.Length - pos - 1);
            else
                return line;
        }
    }
}

【问题讨论】:

  • 以下哪一项更快? line.Substring(pos + 1) 与 line.Substring(pos + 1, line.Length - pos - 1)。我想你之前测试过,然后选择了后者?!
  • 这并不慢。在我看来,添加 RegEx 将是不必要的开销。
  • 您可以将 pos+1 移动到一个变量中,并将其用于开始和减法。但是我们说的是纳秒;)但是它可以节省+1和-1。也是纳秒。将 line.IndexOf('}') 更改为 line.IndexOf('}', 8, line.Length)。保存一个方法调用并扫描起始字节。

标签: c# text performance


【解决方案1】:

您可以尝试并行处理,因为它看起来不需要同步处理。使用 PLINQ 的并行 foreach 可以解决问题。

但是如果你不能等到 VS2010 正式发布,你可以试试Poor Man's Parallel.ForEach Iterator by Emre Aydinceren

【讨论】:

    【解决方案2】:

    这种方法似乎很快就安静下来了。但是从您拥有的字符串中,我得出结论,该名称通常小于 {URL}。您可以使用 .LastIndexOf() 方法。我认为它从字符串的末尾开始

    【讨论】:

    • 我尝试将 LastIndexOf 与 Remove 结合使用并获得了几个百分比的增益,但仅当分隔符接近输入字符串的末尾时。当我把它移到开头时,事情又变慢了。当然,如果实际数据总是符合这个限制,那么 OP 可以利用它。
    【解决方案3】:

    假设您确实在这里找到了答案。我认为您需要考虑下一个查看您的代码的人的“解决方案”会是什么样子。

    我将编写更具可读性的代码,而不是每天几毫秒。

    【讨论】:

    • 除非您需要每秒处理几百万条记录。
    • @Matthew Whited:给定的代码在我可怜的笔记本电脑 (ark.intel.com/Product.aspx?id=29761) 上成功处理了 1,000,000 个字符串,耗时 0.0875438 秒,这意味着它可以在一秒钟内处理 11,422,853 个字符串。因此,每秒超过几百万。
    【解决方案4】:

    您是否尝试过使用 Regex 和/或使用字符串生成器而不是字符串?

    【讨论】:

      【解决方案5】:

      如果你改变了空间的速度,你可以在给定的数组中循环一次,然后复制'{.*}'以外的字符。这将节省两个调用(.IndexOf() 和 .Substring())。

      【讨论】:

        【解决方案6】:

        您确定这是您代码中的瓶颈吗?您对这种方法的时间要求有何规定?您是否分析过您现在拥有的代码以查看它是否符合这些规范?

        我猜你的代码几乎是最优的。 IndexOfSubstring 都调用 unsafe 代码来执行各种花哨的优化,除非您也使用 unsafe 路线,否则您将无法使用这些优化。如果你这样做,你最终将重写IndexOfSubstring

        因此,除非此代码明确成为您代码中的瓶颈,并且您对该方法的时间要求有合理的规范,否则我会将您的精力集中在其他地方。

        【讨论】:

          【解决方案7】:

          到目前为止,最慢的是 Console.WriteLine()。举个例子:

              public void TestCleanSpeed()
              {
                  var start = DateTime.Now;
                  for (var i = 0; i < 10000; i++)
                  {
                      string[] tests = {
                                           "{http://company.com/Services/Types}ModifiedAt",
                                           "{http://company.com/Services/Types}CreatedAt"
                                       };
          
                      foreach (var test in tests)
                      {
                          Console.WriteLine(Clean(test));
                      }
                  }
                  var end = DateTime.Now;
          
                  var ts = end - start;
                  Console.WriteLine(ts);
              }
          

          如果按原样运行,则需要将近六秒钟。然后,删除 Console.WriteLine 并分配 var newTest = Clean(test);。在我的测试中,10000 次执行只用了不到 0.02 秒。

          【讨论】:

          • Console.WriteLine 无关紧要。这甚至不是他询问的Clean 方法的一部分。
          • for(var i=0 .... 循环也无关紧要。我猜 string[] 测试的数组可能很大。你完全描述了一个不同的场景。
          • @Jason - 我读到“有没有办法加快下面的代码?”并假设他的意思是所有他发布的代码。我想我误会了。
          • @Johannes - 我放入了 for 循环,这样它就可以运行多次。当它只运行一次时,它没有记录任何一次执行的时间。
          【解决方案8】:

          唯一的其他方法是使用line.Remove(0, pos + 1);,但我认为在内部是Remove 比Substring 更复杂,因为Remove 也可以从中间删除一些东西。

          所以 Substring() 应该是禁食的。

          【讨论】:

            【解决方案9】:

            您可以将您的字符串转换为XName 并获取名称部分,如下所示。

            ((System.Xml.Linq.XName)"{http://company.com/Services/Types}ModifiedAt").LocalName
            

            【讨论】:

            • 很有趣,也许可以在其他地方使用它,但在这个例子中它使它慢了大约 3 倍
            【解决方案10】:
            line.Substring(line.IndexOf('}') + 1);
            

            稍微快一点。

            【讨论】:

              【解决方案11】:

              而不是你的 foreach...

              for( int i=0;i<tests.Length;i++)
                   Console.WriteLine( tests[i].Replace("}",null ) );
              

              【讨论】:

              • 这不只是替换右大括号,而不是之前的所有内容吗?
              • 是的...我的错...但是,从您的代码中,您不需要 Substring 上的辅助参数作为长度。如果您只提供起始位置,它将从该点返回字符串的所有其余部分。
              猜你喜欢
              • 1970-01-01
              • 2013-04-24
              • 1970-01-01
              • 2013-03-04
              • 2021-01-08
              • 2015-07-02
              • 2021-09-20
              • 2012-12-16
              相关资源
              最近更新 更多