【问题标题】:How to validate a series of unique numbers?如何验证一系列唯一编号?
【发布时间】:2011-10-17 12:15:24
【问题描述】:
validates_format_of            :order_of_importance, :on => :create, :with => /^[1-3]{3}$/,
                             :message => "Order of Importance must have 3 Digits"

现在我可以验证使用的数字是1, 2, 3,但我想确保这些数字不仅被使用,而且每个数字只使用一次。

例如:

应该是有效的数字

2 3 1

1 3 2

1 2 3

不应该是有效的数字:

1 1 2

2 2 1

3 3 3

【问题讨论】:

  • 您是否有特定原因要使用正则表达式?我会使用一种方法。
  • 没有具体原因。这正是我开始的。我想这已经到了一种方法更为重要的地步。既然如此,你将如何编写方法?
  • 老实说,我可能只会做一个 uniq!看看它是否和原来的大小一样。我有时有点懒。 (假设它们在一个数组中。)也可以将它们转储到地图中并比较数组/地图的大小。
  • 同意 Dave 这个任务可以用str.split('').uniq.length == 3 之类的东西轻松解决,而且很难找到合适的正则表达式

标签: ruby-on-rails regex validation


【解决方案1】:
if subject =~ /\A(?:\A(?=[1-3]{3}\Z)(\d)(?!\1)(\d)(?!(?:\1|\2))\d\Z)\Z/
    # Successful match
else
    # Match attempt failed
end

这将匹配一个在 1-3 范围内恰好有 3 个数字且没有重复数字的字符串。

细分:

"
^              # Assert position at the beginning of the string
(?=            # Assert that the regex below can be matched, starting at this position (positive lookahead)
   [1-3]          # Match a single character in the range between “1” and “3”
      {3}            # Exactly 3 times
   \$              # Assert position at the end of the string (or before the line break at the end of the string, if any)
)
(              # Match the regular expression below and capture its match into backreference number 1
   \\d             # Match a single digit 0..9
)
(?!            # Assert that it is impossible to match the regex below starting at this position (negative lookahead)
   \\1             # Match the same text as most recently matched by capturing group number 1
)
(              # Match the regular expression below and capture its match into backreference number 2
   \\d             # Match a single digit 0..9
)
(?!            # Assert that it is impossible to match the regex below starting at this position (negative lookahead)
   (?:            # Match the regular expression below
                     # Match either the regular expression below (attempting the next alternative only if this one fails)
         \\1             # Match the same text as most recently matched by capturing group number 1
      |              # Or match regular expression number 2 below (the entire group fails if this one fails to match)
         \\2             # Match the same text as most recently matched by capturing group number 2
   )
)
\\d             # Match a single digit 0..9
\$              # Assert position at the end of the string (or before the line break at the end of the string, if any)
"

【讨论】:

    【解决方案2】:

    检查所有 3 项不是更容易吗!有效排列?

    编辑:

    但是为了迎接挑战: (?:1(?!\d*1)|2(?!\d*2)|3(?!\d*3)){3}

    它使用negative lookaheads 来确保号码只被选中一次。

    编辑:

    Checked with rubular.com.

    【讨论】:

      【解决方案3】:

      您可以将字符串分解为 3 个数字。 a、b 和 c。

      那么你有很多方法可以检查。例如

      min val ==1 and max==3 and sum=6

      将 3 放入一个集合中(希望 ruby​​ 有集合类型),集合的大小应该是 3。

      等等。

      正则表达式可能不是解决这个问题的最佳工具。

      【讨论】:

        【解决方案4】:

        正如其他人已经说过的,最好使用方法或其他东西检查唯一性。但是如果你有理由使用正则表达式,那么正则表达式看起来像这样

        ^(\d)\s*(?!\1)(\d)\s*(?!\1|\2)(\d)$
        

        它在每个数字上使用负前瞻来通过检查已经捕获的组来验证重复。如果你只需要检查 1,2 和 3 那么你可以使用这个

        ^([123])\s*(?!\1)([123])\s*(?!\1|\2)([123])$
        

        【讨论】:

          【解决方案5】:

          我强烈推荐[在线正则表达式生成器][1]

          [1]:http://www.gskinner.com/RegExr/免疑

          【讨论】:

          • 哎呀,Dave,抱歉,但在某种程度上可能对 QO 有所帮助
          • 同意,但更适合作为评论。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-04-30
          • 2015-05-15
          • 2021-09-11
          • 2011-06-19
          • 2012-10-10
          • 1970-01-01
          相关资源
          最近更新 更多