我想从字符串中删除“无合作”的括号。
即,除非字符串中的(
后面跟着)
,否则应删除所有)
。同样,应该删除字符串中某处(
之前没有"(a)".remove_unmatched_parents # => "(a)"
"a(".remove_unmatched_parents # => "a"
")a(".remove_unmatched_parents # => "a"
的所有{{1}}。
理想情况下,算法也会考虑嵌套。
E.g:
{{1}}
答案 0 :(得分:7)
而不是正则表达式,或许考虑下推自动机。 (我不确定Ruby正则表达式是否可以处理这个,我相信Perl可以)。
(非常简单的)过程可能是:
对于输入字符串中的每个字符:
在过程结束时,如果seen_parens是> 0然后从最后开始删除那么多的parens。 (可以使用堆栈或递归将此步骤合并到上述过程中。)
整个过程为O(n)
,即使开销相对较高
快乐的编码。
答案 1 :(得分:3)
以下使用oniguruma。如果您使用ruby1.9,Oniguruma是内置的正则表达式引擎。如果您使用的是ruby1.8,请参阅:oniguruma。
<强>更新强>
我一直懒得复制并粘贴别人的正则表达式。它似乎有问题。
所以现在,我写了自己的。我相信它现在应该有效。
class String
NonParenChar = /[^\(\)]/
def remove_unmatched_parens
self[/
(?:
(?<balanced>
\(
(?:\g<balanced>|#{NonParenChar})*
\)
)
|#{NonParenChar}
)+
/x]
end
end
(?<name>regex1)
将(子)正则表达式regex1
命名为name
,并使其可以被调用。?g<name>
将是代表regex1
的子目标。请注意,?g<name>
不代表与regex1
匹配的特定字符串,但它代表regex1
本身。实际上,可以在?g<name>
中嵌入(?<name>...)
。 更新2
这更简单。
class String
def remove_unmatched_parens
self[/
(?<valid>
\(\g<valid>*\)
|[^()]
)+
/x]
end
end
答案 2 :(得分:2)
构建一个简单的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
运行产量:
wesbailey@feynman:~/code_katas> ruby test.rb
(a)()(asdf)
我不同意修改String类的人,因为你永远不应该打开标准类。正则表达式对于解析器而言非常脆弱且难以支持。我无法想象现在回到以前的解决方案6个月并试图记住他们在做什么!
答案 3 :(得分:1)
这是我的解决方案,基于@ 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
答案 4 :(得分:0)
算法:
Java代码: 出席@ http://a2ajp.blogspot.in/2014/10/remove-unmatched-parenthesis-from-given.html