【问题标题】:Better way to write "matching balanced parenthesis" program in Ruby用 Ruby 编写“匹配平衡括号”程序的更好方法
【发布时间】:2014-03-02 00:12:04
【问题描述】:

这个方法应该接受一个字符串,并检测字符串中的括号 '(' '{' '[' 是否用相应的(相反的)括号正确关闭。

首先,有没有一种更优雅、更紧凑的方式来写这个位而不使用所有的“或”(||):

            split_array.each do |i| 
              if (i == "{" || i == "(" || i == "[")
                  left.push(i)
                else (i == "}" || i == ")" || i == "]")
                  right.push(i)
                end
             end

我的第二个问题是,这段代码很糟糕(见下文)吗?看来我应该能够用更少的行来写这个,但从逻辑上讲,我还没有想出另一个解决方案(还没有。) 该代码适用于大多数测试,但此测试返回 false(请参阅底部的所有驱动程序测试): p valid_string?("[ ( text ) {} ]") == true

任何批评将不胜感激! (另外,如果有更好的部分可以发布这个,请告诉我) 谢谢!

def valid_string?(string)

    opposites = { "[" => "]", "{" => "}", "(" => ")", "]" => "[", "}" => "{", ")" => "(" }

        left = Array.new
        right = Array.new
        return_val = true

        split_array = string.split(//)
        split_array.delete_if { |e| e.match(/\s/) }

          split_array.each do |i| 
          if (i == "{" || i == "(" || i == "[")
              left.push(i)
            else (i == "}" || i == ")" || i == "]")
              right.push(i)
            end
          end

        # p left
        # p right

        left.each_index do |i|
          if left[i] != opposites[right[i]]
              return_val = false
          end
        end  
        return_val
    end 

    p valid_string?("[ ] } ]") == false
    p valid_string?("[ ]") == true
    p valid_string?("[  ") == false                 
    p valid_string?("[ ( text ) {} ]") == true    
    p valid_string?("[ ( text { ) } ]") == false  
    p valid_string?("[ (] {}") == false 
    p valid_string?("[ ( ) ") == false

-------更新:尝试了一些不同的方法后,我的重构是这样的:-----------

def valid_string?(str)

    mirrored = { "[" => "]", "{" => "}", "(" => ")" }
    open_brackets = Array.new

    split_str_array = str.split("")

    split_str_array.each do |bracket| 
      if bracket.match(/[\[|\{|\(]/) then open_brackets.push(bracket)
      elsif bracket.match(/[\]|\}|\)]/)
        return false if mirrored[open_brackets.pop] != bracket
      end
    end
    open_brackets.empty?
end 

【问题讨论】:

  • 这属于Code Review
  • 感谢您的反馈。有没有办法移动它?
  • 我将其标记为 Mod.. 他们应该可以为您移动它
  • 除非你写得更便于读者阅读,否则你不会得到好的答案。不要从一大段代码开始而不解释它的作用。您在最后编写代码的用法。你应该把它写在开头。在我们最后到达那部分之前,您的所有代码都只是毫无意义的垃圾。
  • 为什么不每次看到合适的右括号就弹出?为什么是两个堆栈?

标签: ruby if-statement conditional-statements


【解决方案1】:

我的方法如下:

def valid_string?(string)
  open_paren = ['[','{','(']
  close_paren = [']','}',')']
  open_close_hash = {"]"=>"[", "}"=>"{", ")"=>"("}
  stack = []
  regex = Regexp.union(close_paren+open_paren)
  string.scan(regex).each do |char|
    if open_paren.include? char
      stack.push(char)
    elsif close_paren.include? char
      pop_val = stack.pop
      return false if pop_val != open_close_hash[char]
    end
  end
  open_paren.none? { |paren| stack.include? paren }
end 

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

Algorithm :

  1. 声明一个字符栈S
  2. 现在遍历表达式字符串 exp。
    • 如果当前字符是起始括号(‘(‘‘{‘‘['),则将其压入堆栈。
    • 如果当前字符是右括号(')''}'']'),则从堆栈中弹出,如果弹出的字符是匹配的起始括号,则可以,否则括号不平衡。
  3. 完全遍历后,如果有一些起始括号留在 堆栈然后“不平衡”

【讨论】:

    【解决方案2】:

    最短的正则表达式可能是:

    def valid_string? orig
      str = orig.dup
      re = /\([^\[\](){}]*\)|\[[^\[\](){}]*\]|\{[^\[\](){}]*\}/
      str[re] = '' while str[re]
      !str[/[\[\](){}]/]
    end
    

    【讨论】:

      【解决方案3】:

      怎么样:

      class Brackets
        def self.paired?(s)
          stack = []
          brackets = { '{' => '}', '[' => ']', '(' => ')' }
      
          s.each_char do |char|
            if brackets.key?(char)
              stack.push(char)
            elsif brackets.values.include?(char)
              return false if brackets.key(char) != stack.pop
            end
          end
          stack.empty?
        end
      end
      
      
      Brackets.paired?("[ ] } ]") # => false
      Brackets.paired?("[ ]") # => true
      Brackets.paired?("[  ") # => false
      Brackets.paired?("[ (] {}") # => false
      Brackets.paired?("[ ( ) ") # => false
      Brackets.paired?("[ ( text { ) } ]") # => false
      Brackets.paired?("[ ( text ) {} ]") # => true
      

      【讨论】:

        【解决方案4】:

        另一种方式:

        s = str.gsub(/[^\{\}\[\]\(\)]/, '')
        while s.gsub!(/\{\}|\[\]|\(\)/, ''); end
        s.empty?
        
        Ex 1
        str = "(a ()bb [cc{cb (vv) x} c ]ss) "
        s = str.gsub(/[^\{\}\[\]\(\)]/, '') #=> "(()[{()}])"
        while s.gsub!(/\{\}|\[\]|\(\)/, '') do; end
          s => "([{}])" => "([])" => "()" => "" gsub!() => nil
        s.empty? #=> true
        
        Ex 2
        str = "(a ()bb [cc{cb (vv) x] c }ss) "
        s = str.gsub(/[^\{\}\[\]\(\)]/, '')  #=> "(()[{()]})"
        while s.gsub!(/\{\}|\[\]|\(\)/, '') do; end
          s => "([{]})" gsub!() => nil 
        s.empty? #=> false
        

        【讨论】:

          【解决方案5】:

          这应该提供相同的功能

          def valid_string?(string)
            #assume validity
            @valid = true
            #empty array will be populated inside the loop
            @open_characters = []
            #set up a hash to translate the open character to a closing character
            translate_open_closed = {"{" => "}","["=>"]","("=>")"}
            #create an array from the string loop through each item 
            string.split('').each do |e| 
              #adding it to the open_characters array if it is an opening character
              @open_characters << e if e=~ /[\[\{\(]/
              #if it is a closing character then translate the last open_character to 
              #a closing character and compare them to make sure characters are closed in order
              #the result of this comparison is applied to the valid variable
              @valid &= e ==  translate_open_closed[@open_characters.pop] if e=~ /[\]\}\)]/
            end
            #return validity and make sure all open characters have been matched
            @valid &= @open_characters.empty?
          end
          

          您也可以使用注入来执行此操作,但它会不太透明。

          【讨论】:

          • 布尔对象是 +=。所以像这样的valid = true; valid &amp;= false 所以valid 现在将是false
          • 噢……对我来说这看起来很奇怪,所以我认不出来。 :-)
          • @engineersmnky 太酷了。我特别喜欢与 RegExp 的匹配,而不是我拥有它的方式。如果我错了,请纠正我,正则表达式中的"|" 基本上是在说“匹配这个“或”这个“或”这个吗? e =~ /[\[|\{|\(]/e.match(/[\[|\{|\(]/) 一样吗?
          • 是的,正则表达式中的单管道| 表示“或”。 =~ 实际上返回第一个匹配项的索引 .match() 返回一个 MatchData 对象,但是它们的用途相似。
          • @engineersmnky 实际上,您使用 | INSIDE 一个正则表达式字符类,它按字面意思处理它。您的正则表达式现在也将匹配“|”特点。 '|' =~ /[\[|\{|\(]/ # =&gt; 0。您应该在字符类中省略|。字符类已经是“或”,即/[abc]/ 表示“a”或“b”或“c”。或者,您可以从字符类中删除字符,即/\[|\{|\(/(删除了定义字符类的打开[和关闭])。
          【解决方案6】:

          这是模拟面试编码挑战的一部分。就我而言,{ "(" =&gt; ")", "[" =&gt; "]" } 中还传递了一个括号映射,这意味着括号的类型可能会有所不同。

          def balanced_parens(string, parens_map)
            # where we throw opening parens
            opening_parens = []
            i = 0
            while i < string.length
              # if current index is opening paren add to array
              if parens_map.keys.include? string[i]
                opening_parens << string[i]
              # if current index is closing paren, remove last item from opening_array 
              elsif parens_map.values.include? string[i]
                popped_paren = opening_parens.pop
                # checking that closing parens at current index is a match for last open parens in opening_array
                return false if string[i] != parens_map[popped_paren]
              end
              i += 1
            end
            # if opening_parens array is empty, all parens have been matched (&& value = true)
            opening_parens.empty?
          end
          

          【讨论】:

            【解决方案7】:
            def valid_string?(exp)
              return false if exp.size % 2 != 0
              curly = "{}"
              square = "[]"
              parenthesis = "()"
              emptystr = ""
              loop do 
               old_exp = exp
               exp = exp.sub(curly, emptystr)
               break if exp == emptystr
               exp = exp.sub(square, emptystr)
               break if exp == emptystr
               exp = exp.sub(parenthesis, emptystr)
               break if exp == emptystr || exp == old_exp
             end
             exp == emptystr
            end
            
            

            【讨论】:

              【解决方案8】:

              你可以试试这个方法:

              def balanced_brackets?(string)
                # your code here
                stack = []
                opening_bracket = ['{','[', '(']
                closing_bracket = ['}', ']', ')']
                string.chars.each do |char|
                  if opening_bracket.include?(char)
                    stack << char
                  elsif closing_bracket.include?(char)
                    value = stack.pop
                    return false if opening_bracket.index(value) != closing_bracket.index(char)
                  end
                end
                
                stack.empty?
              end
              

              如果您想了解伪代码,请尝试coursera 的此链接(从 0:56 开始)。

              【讨论】:

                猜你喜欢
                • 2011-12-15
                • 1970-01-01
                • 2021-07-07
                • 2016-06-03
                • 2010-10-07
                相关资源
                最近更新 更多