代码之家  ›  专栏  ›  技术社区  ›  Ethan

如何在Ruby中解析包含通配符和字符类的字符串?

  •  0
  • Ethan  · 技术社区  · 15 年前

    我想写一个脚本,其中包含一个可能如下所示的参数:

    abc(ag)de*
    

    a , b , c 是文字字符。

    (ag) 表示“A”或“G”。

    * 指任何一个字母或数字。

    我希望脚本创建一个包含输入可以表示的所有可能字符串的数组。(目的是检查是否有可用的域名。)

    输入也可能是 abc(ag)de(mnlop) 在角色类中有更多。

    似乎第一个任务是将其拆分为一个或多个数组,所以第一个示例是…

    [
      ['a'],
      ['b'],
      ['c'],
      ['a', 'g'],
      ['d'],
      ['e'],
      [
        'a', 'b', 'c', 'd', 'e', 'f', 'g',
        # etc...
      ]
    ]
    

    这就是我被卡住的地方。我不知道怎么把它分成那样的碎片。

    关于如何接近它有什么建议吗?

    3 回复  |  直到 15 年前
        1
  •  5
  •   sris    15 年前

    这里有一个非常紧凑的解决方案。它决不会针对性能进行优化,这会对您提供的模式造成一些限制,例如,太多通配符可能不是最佳选择。

    下面是代码

    input1 = "abc(ag)de*"
    input2 = "abc(ag)de(mnlop)"
    
    class Array
      def append_suffixes!(suffixes)
        self.replace suffixes.map { |a| self.map { |p| p + a }}.flatten
      end
    end
    
    def generate_combinations(pattern)
      combinations = [""]
      pattern.scan(/\(([^)]+)\)|(\*)|(\w+)/) do |group,wildcard,other|
        new_suffixes = case
          when group    : group.split('')
          when wildcard : [*'a'..'z']
          when other    : other
          else raise "Unknown match!"
        end
        combinations.append_suffixes! new_suffixes
      end
      combinations
    end
    
    p generate_combinations(input1)
    p generate_combinations(input2)
    p generate_combinations("**").size
    

    运行上述代码的输出(稍微编辑一下):

    ["abcadea", "abcgdea", "abcadeb", "abcgdeb", "abcadec", 
     "abcgdec", "abcaded", "abcgded", "abcadee", "abcgdee", 
     "abcadef", "abcgdef", "abcadeg", "abcgdeg", "abcadeh", 
     "abcgdeh", "abcadei", "abcgdei", "abcadej", "abcgdej", 
     "abcadek", "abcgdek", "abcadel", "abcgdel", "abcadem", 
     "abcgdem", "abcaden", "abcgden", "abcadeo", "abcgdeo", 
     "abcadep", "abcgdep", "abcadeq", "abcgdeq", "abcader", 
     "abcgder", "abcades", "abcgdes", "abcadet", "abcgdet", 
     "abcadeu", "abcgdeu", "abcadev", "abcgdev", "abcadew", 
     "abcgdew", "abcadex", "abcgdex", "abcadey", "abcgdey", 
     "abcadez", "abcgdez"]
    
    ["abcadem", "abcgdem", "abcaden", "abcgden", "abcadel", 
     "abcgdel", "abcadeo", "abcgdeo", "abcadep", "abcgdep"]
    
    676 # The number of two letter words i.e. 26*26
    

    请随时询问您是否对上述代码有任何疑问。

        2
  •  1
  •   unwind    15 年前

    如果你的*只有一个字符,那么我想这至少是可以解决的。如果它的意思是“任何字符的零个或多个”,那么你的解空间就好像是在无穷大的边界上,因此很难作为一个实际的具体值返回。

    我想我可以通过某种方式将变量部分分离出来,计算出每个变量支持多少个变量,然后(概念上)以嵌套的方式循环所有变量,为最里面的循环的每个迭代形成一个输出字符串。

    对于“abc(ag)de*”的示例字符串,这可以归结为(python-ish伪代码,my-ruby不是供公共使用的):

    results = []
    for x in "ag":
      for y in "abcdefghijklmnopqrstuvwxyz":
        results.append("abc%sde%s" % (x, y))
    

    最后一行字符串中的%s是格式说明符,s的意思是“string”,它将导致在字符串插入到该位置后,从元组到%运算符右侧的相应值。

        3
  •  1
  •   Sarah Mei    15 年前

    您本质上要求的是获取一个regexp并生成它匹配的所有字符串。

    那是 Ruby Quiz #143 . 看看左侧的解决方案。