我必须编写一个方法,该方法接受一个字符串,如果方括号不为空,括号和大括号正确关闭,则返回true;否则返回false。
这就是我所拥有的:
def empty_brackets?(string)
%w[ () [] {} ].none?(&string.method(:include?))
end
def valid_string?(string)
match_count = 0
string.each_char do |c|
match_count += 1 if [ '[', '{', '(' ].include?(c)
match_count -= 1 if [ ']', '}', ')' ].include?(c)
end
match_count == 0
end
我认为我的valid_string?
方法不太可靠,但最重要的是,它没有通过括号(例如)somebrackets(
)顺序错误的测试。您能建议如何解决吗?
答案 0 :(得分:3)
我的尝试,将所有左括号放入一个数组中,如果匹配则弹出右括号:
year month day Total
2017 7 24 476.00
2017 7 26 1992.20
2017 7 30 877.50
2017 7 3345.70
2017 8 2 2362.40
2017 8 2362.40
2017 5708.10
5708.10
答案 1 :(得分:1)
这是一个非常有效的版本。它使用正则表达式,并将所有的花括号({}[]()
)拉成一个小的数组,然后不断摆动对直到没有剩余。第二个它找到一个不匹配的对,它退出并返回false。它也不会将字符串拆分为char数组,因为它将使用两倍的内存(一次用于整个字符串,再一次用于将字符串拆分为单个字符)。
BRACKET_PAIRS = { '{' => '}', '[' => ']', '(' => ')' }
BRACKET_REGEX = /#{BRACKET_PAIRS.to_a.flatten.map { |v| Regexp.escape(v) }.join('|')}/
def valid?(string)
brackets = string.scan(BRACKET_REGEX)
while brackets.size > 0
first = brackets.shift
last = brackets.pop
return(false) unless BRACKET_PAIRS[first] == last
end
return(true)
end
如果根本没有括号,此代码将返回true。
如果您不喜欢这样做,请执行以下操作:
BRACKET_PAIRS = { '{' => '}', '[' => ']', '(' => ')' }
BRACKET_REGEX = /#{BRACKET_PAIRS.to_a.flatten.map { |v| Regexp.escape(v) }.join('|')}/
def valid?(string)
brackets = string.scan(BRACKET_REGEX)
return(false) unless brackets.size > 0 # this line is added
while brackets.size > 0
first = brackets.shift
last = brackets.pop
return(false) unless BRACKET_PAIRS[first] == last
end
return(true)
end
作为旁注,您将希望避免像在示例中那样在循环中创建数组:
string.each_char do |c|
match_count += 1 if [ '[', '{', '(' ].include?(c)
match_count -= 1 if [ ']', '}', ')' ].include?(c)
end
此代码将在您的string
变量中创建两个数组和每个字符6个字符串。这是非常低效的,您将使用比必要数量更多的RAM和CPU。您至少要使这两个数组在循环外,因为它们不会改变,并且理想情况下甚至使它们成为常数,这样您甚至在每次调用该方法时都不会使其成为数组。在您的程序启动时将其设置为一个,并永久使用它。像这样的小事情实际上会产生很大的不同,尤其是在循环中使用时。
答案 2 :(得分:1)
CLOSE_TO_OPEN = { ']'=>'[', '}'=>'{', ')'=>'(' }
def valid?(str)
str.each_char.with_object([]) do |c,stack|
case c
when '[', '{', '('
stack << c
when ']', '}', ')'
return false unless stack.pop == CLOSE_TO_OPEN[c]
end
end.empty?
end
valid? "[a]{b[c{d}e]fg}" #=> true
valid? "[a]{b[c{d]e}fg}" #=> false
可以通过添加一些puts
语句来看到方法的行为。
def valid?(str)
str.each_char.with_object([]) do |c,stack|
puts "c=#{c}, stack=#{stack}"
case c
when '[', '{', '('
stack << c
puts " stack after 'stack << #{c}' = #{stack}"
when ']', '}', ')'
print " stack.pop (#{stack.last||'nil'})==CLOSE_TO_OPEN[#{c}] " +
"(#{CLOSE_TO_OPEN[c]})=>"
puts stack.last == CLOSE_TO_OPEN[c] ? "true, so continue" :
"false, so return false"
return false unless stack.pop == CLOSE_TO_OPEN[c]
end
end.tap { |stack| puts "At end, '#{stack}.empty?` (#{stack.empty?})" }.empty?
end
valid? "[a]{b[c{d}e]fg}"
c=[, stack=[]
stack after 'stack << [' = ["["]
c=a, stack=["["]
c=], stack=["["]
stack.pop ([)==CLOSE_TO_OPEN[]] ([)=>true, so continue
c={, stack=[]
stack after 'stack << {' = ["{"]
c=b, stack=["{"]
c=[, stack=["{"]
stack after 'stack << [' = ["{", "["]
c=c, stack=["{", "["]
c={, stack=["{", "["]
stack after 'stack << {' = ["{", "[", "{"]
c=d, stack=["{", "[", "{"]
c=}, stack=["{", "[", "{"]
stack.pop ({)==CLOSE_TO_OPEN[}] ({)=>true, so continue
c=e, stack=["{", "["]
c=], stack=["{", "["]
stack.pop ([)==CLOSE_TO_OPEN[]] ([)=>true, so continue
c=f, stack=["{"]
c=g, stack=["{"]
c=}, stack=["{"]
stack.pop ({)==CLOSE_TO_OPEN[}] ({)=>true, so continue
At end, '[].empty?` (true)
#=> true
valid? "[a]{b[c{d]e}fg}"
c=[, stack=[]
stack after 'stack << [' = ["["]
c=a, stack=["["]
c=], stack=["["]
stack.pop ([)==CLOSE_TO_OPEN[]] ([)=>true, so continue
c={, stack=[]
stack after 'stack << {' = ["{"]
c=b, stack=["{"]
c=[, stack=["{"]
stack after 'stack << [' = ["{", "["]
c=c, stack=["{", "["]
c={, stack=["{", "["]
stack after 'stack << {' = ["{", "[", "{"]
c=d, stack=["{", "[", "{"]
c=], stack=["{", "[", "{"]
stack.pop ({)==CLOSE_TO_OPEN[]] ([)=>false, so return false
#=> false