Ruby 从字符串中删除不匹配的括号
我想从字符串中删除“未合作”括号 也就是说,所有的Ruby 从字符串中删除不匹配的括号,ruby,regex,string,recursion,text-processing,Ruby,Regex,String,Recursion,Text Processing,我想从字符串中删除“未合作”括号 也就是说,所有的()都应该被删除,除非它们后面跟一个)。同样,所有)前面没有(字符串中的某个地方应该被删除 理想情况下,算法也会考虑嵌套 例如: 而不是正则表达式,也许考虑下推自动机。(我不确定Ruby正则表达式是否能处理这个问题,我相信Perl的CAN)。 一个(非常琐碎的)过程可能是: 对于输入字符串中的每个字符: 如果它不是一个“(”或“)”,那么只需将其附加到输出中即可 如果它是一个“(”号,则增加一个seen\u parens计数器并将其相加 如果它是
(
)都应该被删除,除非它们后面跟一个)
。同样,所有)
前面没有(
字符串中的某个地方应该被删除
理想情况下,算法也会考虑嵌套
例如:
而不是正则表达式,也许考虑下推自动机。(我不确定Ruby正则表达式是否能处理这个问题,我相信Perl的CAN)。 一个(非常琐碎的)过程可能是:
对于输入字符串中的每个字符:O(n)
,即使开销相对较高
快乐编码。以下使用oniguruma。如果使用ruby1.9,oniguruma是内置的正则表达式引擎。如果使用ruby1.8,请参见此: 更新 我一直懒得复制和粘贴别人的正则表达式。它似乎有问题 所以现在,我写了我自己的。我相信它现在应该起作用了
class String
NonParenChar = /[^\(\)]/
def remove_unmatched_parens
self[/
(?:
(?<balanced>
\(
(?:\g<balanced>|#{NonParenChar})*
\)
)
|#{NonParenChar}
)+
/x]
end
end
以下是我基于@pst算法的解决方案:
class String
def remove_unmatched_parens
scanner = StringScanner.new(dup)
output = ''
paren_depth = 0
while char = scanner.get_byte
if char == "("
paren_depth += 1
output << char
elsif char == ")"
output << char and paren_depth -= 1 if paren_depth > 0
else
output << char
end
end
paren_depth.times{ output.reverse!.sub!('(', '').reverse! }
output
end
end
类字符串
def删除不匹配的参数
scanner=StringScanner.new(dup)
输出=“”
paren_深度=0
而char=scanner.get\u字节
如果char==”(“
paren_深度+=1
输出构建一个简单的LR解析器:
tokenize, token, stack = false, "", []
")(a))(()(asdf)(".each_char do |c|
case c
when '('
tokenize = true
token = c
when ')'
if tokenize
token << c
stack << token
end
tokenize = false
when /\w/
token << c if tokenize
end
end
result = stack.join
puts result
我不同意人们修改String类,因为你不应该打开一个标准类。Regex对于解析器来说非常脆弱,很难支持。我无法想象6个月后回到以前的解决方案并试图记住他们在做什么!算法:
遍历给定的字符串
进行此操作时,跟踪堆栈中的“(”位置
如果找到任何“)”,请从堆栈中删除顶部元素。
- 如果堆栈为空,请从字符串中删除“)”
最后,我们可以有不匹配的大括号的位置,如果有的话
Java代码:
事实上,这是全世界教学中使用的一种无法用正则表达式解析的语言的例子。现在,Ruby的Regexp
比正则表达式强大得多,它们实际上可以解析这种语言,但并不完全可维护。你可以编写一个简单的使用递归下降解析器或下推自动机所需的时间甚至少于您阅读别人交给您的Regexp
所需的时间,更不用说编写自己的了。如果您将Regexp
拆分为多行以放入注释,可能自动机甚至会更短。感谢算法。我的答案是()你看得对吗?@pst上一个确实有问题。所以现在,我自己写了一个不同的正则表达式。这次应该没问题。希望不会爆发。所以,删除不匹配的父母是一个拼写错误吗?我想是的。
class String
def remove_unmatched_parens
scanner = StringScanner.new(dup)
output = ''
paren_depth = 0
while char = scanner.get_byte
if char == "("
paren_depth += 1
output << char
elsif char == ")"
output << char and paren_depth -= 1 if paren_depth > 0
else
output << char
end
end
paren_depth.times{ output.reverse!.sub!('(', '').reverse! }
output
end
end
tokenize, token, stack = false, "", []
")(a))(()(asdf)(".each_char do |c|
case c
when '('
tokenize = true
token = c
when ')'
if tokenize
token << c
stack << token
end
tokenize = false
when /\w/
token << c if tokenize
end
end
result = stack.join
puts result
wesbailey@feynman:~/code_katas> ruby test.rb
(a)()(asdf)