2009-04-22 53 views
0

我想编写一个脚本,它有一个参数可能看起来像这样的:如何解析在Ruby中包含通配符和字符类的字符串?

abc(ag)de* 

abc是文字符号。

(ag)表示“an”或“g”。

*表示任何一个字母或数字。

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

输入也可能是类似于abc(ag)de(mnlop)的地方,其中有超过字符类。

好像第一个任务是把它分割成一个或多个阵列,所以第一个例子是...

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

这是我卡住。我不知道如何将它拆分成这样的片段。

有关如何处理它的任何建议?

+0

“a”和“that”之间的标题中缺少一个词。我不知道什么是正确的单词(“字符串”?),所以你应该修复它;) – OregonGhost 2009-04-22 09:33:54

+0

你可能会发现我在http://stackoverflow.com/questions/710670/c-permutation发布的C#答案数组列表/ 710716#710716有帮助。在你的情况下,数组就是那些你已经为第一个stask生成的数组。基本的递归算法应该相对容易转化为解决问题的方案。但我不认识Ruby,所以我把它留给你或别人。 – Brian 2009-04-22 16:04:25

回答

5

这是一个非常紧凑的解决方案。它不会针对性能进行优化,从而对您提供的模式施加一些限制,例如,太多的通配符可能不是最好的主意。

下面的代码

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 

,请随时问,如果您对上面的代码中的任何问题。

1

如果你的*表示只有一个字符,那么我猜这至少是可以解决的。如果它的意思是“零个或更多的任何字符”,那么感觉就好像你的解决方案空间接近无限大,因此将很难作为实际的具体值返回。

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

有关的例子字符串“abc(AG)德*”,这将归结到这一点(Python的ISH伪代码,我的Ruby是不要为公共使用):

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

的最后一行字符串中的%s是一个格式说明符,s只是表示“字符串”,并且会在该字符串在该位置进行插值后,将元组中相应的值引至%运算符的右侧。

+0

星星意味着只有一个字符。 – Ethan 2009-04-22 09:39:32

1

你基本上要求的是采取正则表达式并生成匹配的所有字符串。

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

相关问题