【问题标题】:How to efficiently determine if a string starts with a number and then get all following numbers up until the first non-numeric character?如何有效地确定字符串是否以数字开头,然后获取所有后续数字,直到第一个非数字字符?
【发布时间】:2018-02-26 22:49:01
【问题描述】:

我需要对一些包含如下数据的字符串进行排序:

var strings = new List<string>{"2009 Arrears","2008 Arrears","2008 Arrears Interest","2009 Arrears Interest"};

他们希望结果是这样排序的:

  1. “2009 年欠款”
  2. “2009年欠款利息”
  3. “2008年欠款”
  4. “2008年欠款利息”

看来我需要创建一个函数来查看字符串是否以数字开头。如果是这样,该函数将获取所有数字,直到第一个字符,并对数字结果进行降序排序,然后对剩余的字符进行升序排序。我在尝试编写一个获取字符串中所有起始数字的方法时遇到了麻烦。有什么有效的方法来做到这一点?

【问题讨论】:

标签: c# string


【解决方案1】:
public int GetLeadingNumber(string input)
{
    char[] chars = input.ToCharArray();
    int lastValid = -1;

    for(int i = 0; i < chars.Length; i++)
    {
        if(Char.IsDigit(chars[i]))
        {
            lastValid = i;
        }
        else
        {
            break;
        }
    }

    if(lastValid >= 0)
    {
        return int.Parse(new string(chars, 0, lastValid + 1));
    }
    else
    {
        return -1;
    }
}

虽然这绝对是最有效的,但其他海报提供的正则表达式解决方案显然更简洁,可能更清晰,具体取决于您将对字符串进行多少处理。

【讨论】:

    【解决方案2】:

    一个正则表达式可以很好地拆分它:

    var match = Regex.Match(text, @"^(\d+) (.*)$");
    

    那么match.Groups[0].Value是年份,match.Groups[1].Value是标题(“欠款”、“欠款利息”等)

    您可以使用 LINQ 应用排序(年份降序,标题升序):

    string[] titles = new[] { "2008 Arrears", "2009 Arrears" };
    
    var sortedTitles = 
        from title in titles
        let match = Regex.Match(title, @"^(\d+) (.*)$")
        orderby match.Groups[0].Value descending, match.Groups[1].Value
        select title;
    
    listBox.ItemsSource = sortedTitles.ToArray();  // for example
    

    正则表达式可能不是最快的解决方案;这是一个使用 LINQ 仍然保持整洁的替代方案:

    var sortedTitles =
        from title in titles
        let year = new string(title.TakeWhile(ch => char.IsDigit(ch)).ToArray())
        let remainder = title.Substring(year.Length).Trim()
        orderby year descending, remainder
        select title;
    

    【讨论】:

    • 请注意,此表达式将要求数字后跟一个空格(除非使用 IgnoreWhitespace 选项创建/调用正则表达式)。
    • 是的——我假设空格是字符串的保证元素。
    • 我知道它是一个很晚的修饰符,但由于你使用了贪婪的 \d+,你只能用“?”来跟进空格。所以这不是强制性的。您也可以,如果您的起始编号是最近一年(实际上超过 1000),出于性能原因使用 @"^(\d{4}) ?(.*)$" (如果您这么说,引擎会更快)查找四位数字。但是您必须为开始日期中有错误的字符串做好准备。无论如何您都应该这样做)
    猜你喜欢
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    • 2012-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-11
    相关资源
    最近更新 更多