使用Ruby on Rails中的正则表达式定义范围

时间:2014-03-10 15:03:56

标签: ruby-on-rails ruby regex

我有这段代码:

(1..40).map(&:to_s).grep(/[2-3][0-9]/)

因此,当我输入[2-3][0-9]时,它将打印范围内的所有数字(介于20和39之间)。如何在不定义范围的情况下执行此操作(即,在这种情况下,它是" 1..40")因此它适用于我在括号中键入的任何正则表达式?

类似的代码
(1..40).map(&:to_s).grep(/[2-3][0-9]/) 

没有(1..40).map部分就可以使用。

2 个答案:

答案 0 :(得分:2)

好的,这太糟糕了,你真的可能真的不想这样做,你只是觉得你这样做。但是,FWIW:

def this_is_awful(string)
  results = []
  string.split("|").each do |section|
    #example section is "5[0-3][2-4]"
    section_digits = []
    section.split(/[\[\]]+/).select{|s| s.size > 0}.each do |range_string|
      range_digits = range_string.split("-").select{|s| s.size > 0}
      arrays = (range_digits[0]..range_digits[-1]).to_a
      section_digits << arrays if arrays.size > 0
    end
    #now we need every combination of these
    section_digits[0].product(*section_digits[1..-1]).each do |combination|
      results << combination unless results.include?(combination)
    end
  end
  #at this point, results will be like [[5, 0, 2], [5, 0, 3], [5, 0, 4], etc].  Sort these and convert them to digits via strings
  results.sort.collect{|arr| arr.join}
end

例如

irb(main):075:0> this_is_awful("5[2-3]")
=> [52, 53]
irb(main):076:0> this_is_awful("5[2-3][3-9]")
=> [523, 524, 525, 526, 527, 528, 529, 533, 534, 535, 536, 537, 538, 539]
irb(main):077:0> this_is_awful("5[2-3][3-9]|10[1-7][3-8]")
=> [523, 524, 525, 526, 527, 528, 529, 533, 534, 535, 536, 537, 538, 539, 1013, 1014, 1015, 1016, 1017, 1018, 1023, 1024, 1025, 1026, 1027, 1028, 1033, 1034, 1035, 1036, 1037, 1038, 1043, 1044, 1045, 1046, 1047, 1048, 1053, 1054, 1055, 1056, 1057, 1058, 1063, 1064, 1065, 1066, 1067, 1068, 1073, 1074, 1075, 1076, 1077, 1078]

顺便说一句,我会说这个问题与Ruby on Rails无关。

编辑:我刚编辑了这个以便更普遍地使用任何可枚举的(因此它也可以用于字母)。您现在可以返回字符串,但如果需要.collect(&:to_i)

,则可以将它们转换为整数

例如

irb(main):122:0>     this_is_awful("a[b-e][f-g]")
=> ["abf", "abg", "acf", "acg", "adf", "adg", "aef", "aeg"]

编辑2:修复了以数组

开头的错误

答案 1 :(得分:0)

你要做的是暴力强迫。它效率低,速度慢。这只是一种错误的方法,所以忘掉RegEx。

您将需要一个真正的算法。所以我为你做了一个......

我将假设你的输入将只包括号码:1,并这样定义的范围:[2-6]或两者的任何组合,导致像的字符串:1[2-3][5-7]9

想象一下,这是一个包含两种元素的可能数字的向量(数组):

  • 可能的数字范围。
  • 固定数字(数字到相同数字的范围)

我们转换输入1[2-3][5-7]9的示例应如下所示:

[ [1,1], [2,3], [5,7], [9,9] ]

此数组中的第一个元素([1,1])是第一个数字的范围,第二个数字的第二个数字([2,3]),依此类推。

将它变成这样的东西相对容易。这是一个包含两个元素的数组数组 - 每个范围的起始和结束编号。

所以你现在需要做的是输出每个可能的值。这可以通过对每个数字进行简单的递归来完成,为每个数字的每个数字开始一个新的分支。

以下是实现递归的示例:

def recursion(array, number = '')
    return if array.empty? # Don't bother if the digits array is empty

    # iterate over each possible value of the current pair
    (array[0][0]..array[0][1]).each do |i|
        if array.length <= 1 # If the digits array is empty (contains only the current range)
            # then an entire number would have been generated, so print it
            puts number + i.to_s
        else
            # Start a new branch passing the array (without the current element)
            # and the generated number until this moment
            recursion(array[1..-1], number + i.to_s)
        end
    end
end

array = [ [1,1], [2,3], [5,7], [9,9] ]

recursion(array)

按照这种方法,您可以尽可能地使功能变得复杂。

我为您提供了如何计算数字本身的例程,但没有提供如何创建我希望您可以处理的array的例程。

这很难实现,当然不包含RegEx的所有功能,但速度很快,会产生数字。

P.S。哇..这花了我一个小时来创建和调试。希望它有所帮助。