【问题标题】:How to check validity of closed brackets, parentheses or brackets in Ruby如何在 Ruby 中检查右括号、圆括号或方括号的有效性
【发布时间】:2014-01-11 21:26:47
【问题描述】:

写一个方法'valid_string?'接受一个字符串。如果括号、圆括号和花括号正确闭合,则返回 true。否则返回 false。

valid_string?("[ ]")                  # returns true
valid_string?("[  ")                  # returns false
valid_string?("[ ( text ) {} ]")      # returns true
valid_string?("[ ( text { ) } ]")     # returns false

我的代码:对所有内容都返回 false。甚至尝试对个别情况使用显式布尔值 {} || () || 等都没有用。对所有内容都返回 true 或 false。是我的驱动代码吗?

def valid_string?(str) 

    if str == ("\[\s+]")
        true
    else
        false
    end
end

更新的解决方案:-------------------------------------------------------- ---- 是的! #match 肯定效果更好!尽管我的最后一行测试代码评估为真。什么时候应该是假的。 . .

def valid_string?(str) 
if str.match "(\\[.+\\])" || "|(\\(\\))" || "|({})"
    return true
else
    return false
    end
end

puts valid_string?("[ ]")                  # returns true
puts valid_string?("[  ")                  # returns false
puts valid_string?("[ ( text ) {} ]")      # returns true
puts valid_string?("[ ( text { ) } ]")     # returns false

【问题讨论】:

  • == 用于比较regex == regex,而不是regex == string。您想使用~=match。看看docs
  • 您不能使用正则表达式来检查括号和前提的顺序,您必须使用 LIFO 数据结构。
  • 这不是您想要使用正则表达式执行的检查。
  • @rullof 你错了。初学者常见的“正则表达式”和“正则语法”混淆。
  • @sawa 怎么了是不是错了?

标签: ruby regex rubular


【解决方案1】:

我认为使用regex 来解决这个问题可能会很复杂。这是一个潜在的解决方案:您可以使用堆栈来记录遍历中的左侧符号,例如{[(。每次遇到正确的符号,只需检查堆栈顶部的符号是否与这个正确的符号匹配。如果不匹配,只需返回false

下面是我的代码:

def valid_string?(str)
  stack = []
  symbols = { '{' => '}', '[' => ']', '(' => ')' }
  str.each_char do |c|
    stack << c if symbols.key?(c)
    return false if symbols.key(c) && symbols.key(c) != stack.pop
  end
  stack.empty?
end

puts valid_string?('[ ]')                  # returns true
puts valid_string?('[  ')                  # returns false
puts valid_string?('[ ( text ) {} ]')      # returns true
puts valid_string?('[ ( text { ) } ]')     # returns false

【讨论】:

  • 这只是必要条件。
  • 那么,您的意思是在某些情况下,一个字符串可以通过我提到的算法,但它仍然是无效字符串?你能给我举个例子吗?
  • 看OP的第二个例子。
  • 我只是省略了详细的处理说明。当然遍历后还要检查栈是否为空。是的,如果堆栈不为空,我们应该在每次遇到正确符号时弹出堆栈一次。我只是对这种方法进行概述,因为我不确定 OP 的问题中是否存在regex 限制:)
  • 非常好,丹。我更喜欢它而不是我的解决方案。一个可能的细化:1.left_symbols = {'{' =&gt; '}', '[' =&gt; ']', '(' =&gt; ')'}; 2.删除right_symbols; 3. 用'left_symbols.key?(c)替换块的内容? stack
【解决方案2】:

只是因为它有趣,我继续解决了这个Ruby方式 :)

class Brackets
  class Bracket
    def initialize(open, close)
      @open = open
      @close = close
      @match_count = 0
    end
    attr_reader :match_count, :open, :close

    def check(c)
      @match_count += 1 if c == @open
      @match_count -= 1 if c == @close
    end
  end

  def initialize
    @brackets = []
    @stack = []
    @valid = true
  end

  def add(open, close)
    @brackets << Bracket.new(open,close)
  end

  def check(c)
    @brackets.each do |b|
      b.check(c)
      @stack.push(c) if c == b.open
      @valid = false if c == b.close and @stack.pop != b.open
    end
  end

  def valid?
    total = 0
    @brackets.each { |b| total += b.match_count }
    total == 0 && @valid == true
  end
end

def valid_string?(str)
  brackets = Brackets.new
  brackets.add('[', ']')
  brackets.add('{', '}')
  brackets.add('(', ')')

  str.each_char { |c| brackets.check(c) }
  brackets.valid?
end

# Our tests
puts valid_string?("[ ]") ? 'true' : 'false'                 # returns true
puts valid_string?("[  ") ? 'true' : 'false'                 # returns false
puts valid_string?("[ ( text ) {} ]") ? 'true' : 'false'     # returns true
puts valid_string?("[ ( text { ) } ]") ? 'true' : 'false'    # returns false
puts valid_string?("[ ( text { } ) ]") ? 'true' : 'false'    # returns true

【讨论】:

    【解决方案3】:

    这是一种不使用正则表达式的方法:

    def valid_string?(str)
      strim = str.gsub(/[^\[\]\(\)\{\}]/,'')
      return true if strim.empty?
      return false if strim.size.odd?
      loop do  
        s = strim.gsub('()','').gsub('[]','').gsub('{}','')
        return true if s.empty?
        return false if s == strim
        strim = s
      end   
    end
    
    p valid_string?("[ ]")               # => true
    p valid_string?("[  ")               # => false
    p valid_string?("[ ( text ) {} ]")   # => true
    p valid_string?("[ ( text { ) } ]")  # => false
    p valid_string?("[ ( text { more text { (more text) }} )]")  # => true
    
    • 首先删除除“()[]{}”之外的所有字符。
    • 如果剩余字符串为空,则返回true
    • 如果剩余字符串包含奇数个字符,则返回 false。
    • 继续删除相邻对 '()'、'[]' 和 '[]' 直到字符串为空,在这种情况下返回 true,或者不能删除更多相邻对且字符串非空,在这种情况下返回 false。

    【讨论】:

    • 我喜欢这个,很优雅。
    • 你让我脸红了,@Donovan。
    • @Cary Swoveland 哇哦!多漂亮!我认为这是一个非常好的解决方案。出于某种原因,我对这个问题的看法过于简单。但似乎它需要比我最初想象的更多的创造力。谢谢!
    【解决方案4】:

    简单的计数程序怎么样?

    def valid_string?(str)
      match_count = 0
    
      str.each_char do |c|
        match_count += 1 if [ '[', '{', '(' ].include?(c)
        match_count -= 1 if [ ']', '}', ')' ].include?(c)
      end
    
      return match_count == 0
    end
    

    【讨论】:

    • 我刚刚意识到这与最后的测试条件不匹配,但我会将答案留给可能不需要那么复杂的东西的其他人。
    • 这个答案可以修改。 (尽管您必须检查 match_point 在任何时候都保持严格的正数,即在循环内)。目前这个答案的问题是它将所有括号字符视为相同。但是您可以通过创建一个辅助方法来解决这个问题,该方法将开始和结束括号字符作为参数,然后在valid_string? 中调用valid_for('(',')',str) &amp;&amp; valid_for('{','}', str) &amp;&amp; valid_for('[',']',str)(其中valid_for 是该辅助方法)。
    • @Donovan 谢谢!我想我一定会试试 asQuirrel 的辅助方法。
    • 我刚刚添加了另一个答案,灵感来自@asQuirreL :)
    【解决方案5】:

    我发现递归在这种情况下工作得非常好。希望这会有所帮助!

    def valid_string?(string)
      bracket_string = string.gsub(/[^\[\]\(\)\{\}]/,'').gsub('()','').gsub('[]','').gsub('{}','')
      return true if bracket_string.empty?
      return false if bracket_string.length.odd?
      return false if bracket_string.include?(string)
      valid_string?(bracket_string)
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-12
      • 2011-09-26
      • 2011-01-31
      • 1970-01-01
      • 1970-01-01
      • 2021-01-11
      • 2016-07-17
      相关资源
      最近更新 更多