【问题标题】:the most efficient way to separate string分隔字符串的最有效方法
【发布时间】:2012-04-12 10:06:31
【问题描述】:

我有这个字符串:

“B82V16814133260”

从中获取两个字符串的最有效方法是什么:

左部分字符串:“B82V” 右部分字符串:“16814133260”

规则是这样的:取出右侧的所有数字并从中创建字符串,然后取出提醒并将其放入另一个字符串中。

这是我的解决方案,但它太笨重了!如何做到又短又高效?

        String leftString = "";
        String rightString="";

        foreach (char A in textBox13.Text.Reverse())
        {
            if (Char.IsNumber(A))
            {
                rightString += A;
            }
            else
            {
                break;
            }
        }

        char[] arr = rightString.ToArray();
        Array.Reverse(arr);

        rightString=new string(arr);
        leftString = textBox13.Text.Replace(rightString, "");

【问题讨论】:

  • efficient 是什么意思?内存效率高还是性能高?
  • 出于好奇,为什么您的解决方案“过于庞大”?对我来说,这似乎是一个很好的功能长度。
  • 我会发布相关的正则表达式,但我向上帝发誓,如果其他人先发布它......
  • 你现在有什么问题吗?
  • @Bob2Chiv 所有的字符串连接都相当低效。 StringBuilder 会有所帮助,但正则表达式可以通过一次和一份副本完成所有工作。

标签: c# string optimization split string-split


【解决方案1】:

这会产生你所期望的:

var given = "B82V16814133260";
var first = given.TrimEnd("0123456789".ToCharArray());
var rest = given.Substring(first.Length);

Console.Write("{0} -> {1} -- {2}", given, first, rest);
//  B82V16814133260 -> B82V -- 16814133260

【讨论】:

  • +1:虽然理论上扫描字符串直到ch < '0' || ch > '9',然后在索引上拆分听起来最快,但需要科学应用程序才能分辨出差异(也许)。
  • 一个优雅的解决方案。我不知道 TrimEnd。
  • 对此的改进是使用'0'..'9'连续的事实来提高性能。例如。 var index = given.Last(ch => ch >= '0' && ch
  • @danny,不幸的是,这将使他失去使用 TrimEnd 的资格,这确实是他回答的中心点。
  • @CMP 我知道,但是,使用 Substring() 两次可以解决问题。
【解决方案2】:

好吧,其他答案可能更好,但我还是写了这个,所以我发布它:

需求:

using System.Text.RegularExpressions;

代码:

string str = "B82V16814133260";
string[] match = Regex.match(str, @"^([\d\w]+?\w)(\d+)$").Groups;
string left = match[1];
string right = match[2];

【讨论】:

  • 这也是一个很好的解决方案!
  • @walkerneo 只是一个有趣的事实,为此运行正则表达式(也编译正则表达式,发布构建)需要 1605.3 秒,或 856.4 倍)所以如果速度是“高效”的,那么正则表达式不是“高效的” '。
  • @payo,好的,谢谢,我也这么认为。但是,如果他的要求发生变化,使得字符串不仅仅以数字结尾,这将更容易修改。我不知道在他的情况下这是否可能,据我所知,这些字符串将始终采用相同的格式,但你永远不知道。
  • 顺便说一句!!!我希望阅读这篇文章的人确实意识到 1605.3 秒是基于我编写的测试(将运行时与同一篇文章中的其他答案进行比较。我认为 Walkemeo 知道这一点,但访问者后来可能没有意识到这一点。显然,运行正则表达式 ONCE 将完成在
【解决方案3】:

这应该很快:

int index = text.Length - 1;
while (index >= 0 && Char.IsDigit(text[index]))
{
    index--;
}
string left = text.Substring(0, index + 1);
string right = text.Substring(index + 1);

【讨论】:

  • 与什么相比非常快?
  • @AshBurlaczenko:没有不必要的stringreversing 分配字符串,也没有array 分配。 应该更快。
  • 其实我会选择这个答案最有可能是一个正确的答案,因为它更清晰,应该比投票最多的更快,即使应该承认投票最多的肯定是“更可爱”。
  • @Tigran 谢谢!最喜欢的答案真的很有趣,我永远不会想到这个。
【解决方案4】:

我将“最有效”理解为“最快”。

我用长字符串写了一个快速测试,运行了 1000 万次。

Austin 使用 TrimEnd 的解决方案在 4.649 秒内运行

我的解决方案在 1.927 秒内运行

    int j = given.Length - 1;

    for (; j >= 0; j--)
    {
      char c = given[j];
      if (c < '0' || c > '9')
      {
        break;
      }
    }

    var first = given.Substring(0, j + 1);
    var rest = given.Substring(j + 1);

请注意,我的构建没有调试(在调试中,我的解决方案较慢,但那是因为 TrimEnd 没有在调试位中运行)。所以,如果你在你的应用程序中运行我的代码,并且正在构建调试,它会更慢。

【讨论】:

    【解决方案5】:

    我喜欢 linq。

        var s = "B82V16814133260";
        var lastNonNumeric = s.Reverse().Where(x => !char.IsDigit(x)).FirstOrDefault();
        var index = s.LastIndexOf(lastNonNumeric);
        var secondString = s.Substring(index + 1);
        var firstString = s.Substring(0, index+1);
    

    可能不是最好或最强大的解决方案,但它适用于您的测试字符串。

    【讨论】:

    • 反向会浪费精力,因为您不需要保留反向结果。 s.Last(ch => '0'
    • 我同意。仍然不如奥斯汀的解决方案,所以我不会费心编辑它。
    【解决方案6】:
     string Source = textBox13.Text;
    
     for (i = Source.Length - 1; i >=0; i--)
     {
          if (! Char.IsNumber(Source[i])
             break;
     }
    
     string leftString = Source.Left(i+1);
     string rightString = Source.Right(i+1,Source.Length-i-1);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-22
      相关资源
      最近更新 更多