【问题标题】:How to parse a string to extract year range values?如何解析字符串以提取年份范围值?
【发布时间】:2010-11-04 00:28:20
【问题描述】:

我收到了更改请求,但我不确定如何最好地处理它。如果客户搜索某些内容,并且他们指定的年份或年份范围大于我们数据库中的数据,我必须返回与我们拥有的最新年份范围相对应的结果。

目前我们在数据库中的结果都遵循以下模式之一:

Thing1 Thing2 S1 // There's some results with no year
Thing1 Thing2 2006-07 Series 6 // there's some results with 'Series X'
Thing1 Thing2 2006-2007 S12 RP // some resuls have SN or SN YZ
Thing1 Thing2 2020-21 S6 // some results don't have a full second year
Thing1 Thing2 2022-2024 S12
Thing1 Thing2 2024 Onwards // the result that matches the final year just has the year & 'Onwards'

世界上有更多关于 Thing1 Thing2 的结果,直到 2060 年,但我们只保留 +14 年的数据,因为 14 年后(比如 2026 年或 2028 年),数据与几年前。

我们拥有的最大年份,存在的最大年份每 2 年增加 2 年。所以在 2012 年,我们将拥有 Thing1 Thing2 2026 Onwards,并且存在的最大值将是 2062。

所以基本上,我需要识别客户端何时搜索 [Thing1 (or) Thing2 with a year range],如果第一年的值大于 [今年 + 14] 我必须返回 [今年 + 14],但前提是当前年份是偶数年,否则我必须返回[今年+13]。

我遇到的麻烦是如何识别不遵循明确定义模式的字符串中间的年份,除了年份范围的第一部分以 4 位数年份开头。

对我来说最好的方法是什么?有人可以建议我如何解决这个问题吗?谢谢。

【问题讨论】:

    标签: c# algorithm string


    【解决方案1】:

    这个正则表达式模式可以很好地工作:\b(?<Year1>\d{4})(?:-(?<Year2>\d{2,4}))?\b

    解释:

    • \b: 是一个词边界,以确保我们完全独立地捕捉年份,而不是作为另一个词的一部分(即没有部分匹配) - 这用于锚定模式的两端
    • (?<Year1>\d{4}):命名捕获组以匹配 4 位数字
    • (-(?<Year2>\d{2,4}))?:这匹配 - 破折号,然后在第二年使用命名捕获组,该组匹配 2-4 个重复数字,因为这些年份的长度不同。左括号和右括号将此模式组合在一起,最后尾随的 ? 使整个组对于不存在第二年的情况是可选的。

    从技术上讲,\d{2,4} 部分接受 07, 107, 2007。显然 3 位数的年份是不正确的。我建议您执行额外的错误检查以捕获此类情况。您可以通过将其更改为 \d{2}|\d{4} 来阻止它,但随后您将匹配 Year1 而不是 Year2 并丢失用户输入。

    代码如下:

    string[] inputs = { "Thing1 Thing2 S1", "Thing1 Thing2 2006-07 Series 6", "Thing1 Thing2 2006-2007 S12 RP", "Thing1 Thing2 2020-21 S6", "Thing1 Thing2 2022-2024 S12", "Thing1 Thing2 2024 Onwards" };
    string pattern = @"\b(?<Year1>\d{4})(-(?<Year2>\d{2,4}))?\b";
    Regex rx = new Regex(pattern);
    
    foreach (var input in inputs)
    {
        Match m = rx.Match(input);
        Console.WriteLine("{0}: {1}", m.Success, input);
        if (m.Success)
        {
            string year1 = m.Groups["Year1"].Value;
            string year2 = m.Groups["Year2"].Value;
            Console.WriteLine("Year1: {0}, Year2: {1}", year1, year2 == "" ? "N/A" : year2);
        }
        Console.WriteLine();
    }
    

    【讨论】:

      【解决方案2】:

      也许只需搜索字符串中的前 4 个数字字符(如果有)并将它们视为年份就可以了吗?

      【讨论】:

        【解决方案3】:

        或像

        这样的正则表达式
        perl -ne '/(\d\d\d\d)-(\d\d(\d\d)?)/; print "$1:$2:$3"'
        

        【讨论】:

          猜你喜欢
          • 2012-03-04
          • 2016-04-25
          • 1970-01-01
          • 2012-11-18
          • 2021-04-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多