【问题标题】:Regex comma separated single digits ordered ascending正则表达式逗号分隔的单个数字按升序排列
【发布时间】:2016-05-13 10:24:11
【问题描述】:

我正在尝试编写一个正则表达式来验证具有以下条件的用户输入(asp.net、c#):

- single digits within a range of 1 - 6
- comma separated, but list should not begin or end with a comma
- digits cannot be repeated
- digits should be in ascending order

例如:

- 1,2,3,4,5,6   - valid
- 2,5,6         - valid
- 4             - valid
- 2,5,6,        - invalid
- 3,6,5         - invalid
- 2,2,5,6       - invalid

到目前为止,我得到了:

^((1,)?(2,)?(3,)?(4,)?(5,)?(6)?)$

问题是数字 1-5 必须后跟逗号,如果它们是唯一输入的数字,则不正确。

【问题讨论】:

  • 无需正则表达式即可轻松完成。正则表达式将无法阅读,太长了。
  • @Wiktor Stribiżew。感谢您的回复。您是否建议我只在 c# 代码中执行检查?另外,无论使用正则表达式是否是最有效的选择,我现在仍然想知道如何在正则表达式中完成它,即使它只是为了学习目的。
  • 不,我不会花 40 分钟的时间在一个没人会使用的模式上。关键是您需要捕获您拥有的每个数字,然后使用条件构造来查看匹配的内容。或者列出所有替代方案的蛮力方法。正则表达式不适用于此类任务
  • 重复检查和排序最好通过编程语言来完成。
  • @CinCout 但他说他希望将此作为正则表达式用于学习目的,而不是因为它是完成任务的正确方法

标签: c# regex csv digit


【解决方案1】:

您可以使用\b 来确保您位于单词的边界,而,* 可以使用逗号或不使用逗号。这导致工作 - 虽然很长

^((1)?(\b,?2)?(\b,?3)?(\b,?4)?(\b,?5)?(\b,?6)?)$

【讨论】:

  • 很好,只需将* 更改为? 即可避免2,,,,,,5,6 通过。 ^((1)?(\b,?2)?(\b,?3)?(\b,?4)?(\b,?5)?(\b,?6)?)$
  • 太好了,谢谢!我仍处于学习正则表达式的早期阶段,之前还没有遇到过 \b 符号,所以我将对其进行更多研究。再次感谢:)
【解决方案2】:

(这是一个愚蠢的答案)

鉴于有六个值,每个值都可以存在或不存在,因此有2^6 = 64 可能的正确值;除了我猜我们想排除根本不存在数字的可能性,所以只有63 可能的正确值。这个正则表达式允许它们并且只允许它们:

^(6|5|5,6|4|4,6|4,5|4,5,6|3|3,6|3,5|3,5,6|3,4|3,4,6|3,4,5|3,4,5,6|2|2,6|2,5|2,5,6|2,4|2,4,6|2,4,5|2,4,5,6|2,3|2,3,6|2,3,5|2,3,5,6|2,3,4|2,3,4,6|2,3,4,5|2,3,4,5,6|1|1,6|1,5|1,5,6|1,4|1,4,6|1,4,5|1,4,5,6|1,3|1,3,6|1,3,5|1,3,5,6|1,3,4|1,3,4,6|1,3,4,5|1,3,4,5,6|1,2|1,2,6|1,2,5|1,2,5,6|1,2,4|1,2,4,6|1,2,4,5|1,2,4,5,6|1,2,3|1,2,3,6|1,2,3,5|1,2,3,5,6|1,2,3,4|1,2,3,4,6|1,2,3,4,5|1,2,3,4,5,6)$

请不要实际使用它。你会让我们俩看起来都很糟糕。

【讨论】:

    【解决方案3】:

    非正则表达式版本。简单而精确

    string str = ",1,  2,3, 4, 5, 6";
    bool valid = false;
    var invalidString = str.Split(',').Any(p =>
    {
        int num = 0;
        return int.TryParse(p, out num);
    });
    if (!invalidString)
    {
        List<int> list = str.Split(',').Select(p => int.Parse(p)).ToList();
        var sorted = list.SequenceEqual(list.OrderBy(p => p));
        var hasDuplicates = list.Count != list.Distinct().Count();
        valid = sorted && !hasDuplicates;
    }
    

    【讨论】:

      【解决方案4】:

      仅出于学习目的,将问题分解为多个部分。

      它必须由一个数字组成,后跟零个或多个逗号加数字。

      ^\d(?:,\d)*$
      

      只有 6 位数字,并且必须按升序排列。因此,只需列出它们及其中间的逗号即可;每个都是可选的。

      ^1?,?2?,?3?,?4?,?5?,?6?$
      

      难点在于以上两个正则表达式必须同时匹配。我们可以在其中一个上使用零宽度前瞻。这将进行匹配,但不会“消耗”任何字符。因此,在它匹配正则表达式的下一部分后,它将从与前瞻相同的位置开始。向前看是通过在(?= 和')' 中包装一个表达式来实现的。给予:

      (?=^\d(?:,\d)*$)
      

      结合这两个正则表达式得到以下结果:

      (?=^\d(?:,\d)*$)^1?,?2?,?3?,?4?,?5?,?6?$
      

      【讨论】:

      • 我不太明白在您最初发布后的展望如何工作,但您的更新使其更加清晰 - 谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多