Scala way to program bunch of if's

后端 未结 4 1344
北恋
北恋 2020-12-08 08:03

I\'m starting out with scala, and trying to apply the functional way to it, but I came out with bunch of nested if\\else constructions which is hard to read, and I wonder is

相关标签:
4条回答
  • 2020-12-08 08:43

    I don't think there is any reason to filter the list before you traverse it. You can just ignore the non parentheses as you traverse the list. I think it is also unnecessary to build the second list. All you really want to know is that the count of open parenthesis is never negative:

    def balance(chars: List[Char]): Boolean = {
      @tailrec
      def _balance(chars: List[Char], count: Int) : Boolean = 
        chars match {
            case Nil => count == 0   // end of the string did we close every open?
            case '(' :: xs => _balance(xs, count+1)  
            case ')' :: xs => (count > 0) && _balance(xs, count-1) 
            case _ => _balance(chars.tail, count) // uninteresting char, skip it
        }
    
      _balance(chars, 0)
    }
    
    0 讨论(0)
  • 2020-12-08 08:46

    Well:

    1. You could start by writing it with else if conditions.
    2. Go ahead an annotate it with tailrec since it's tail-recursive.
    3. The filter condition can be written more simply as Set('(', ')'), which is a function from Char to Boolean
    4. I think you're missing the condition where chars is empty but parenthesis is not.

    So it would look like:

    def balance(chars: List[Char]): Boolean = {
      @tailrec
      def checkParentesys(chars: List[Char], parentesis: List[Char]): Boolean =
        if (chars.isEmpty && parentesis.isEmpty)
          true
        else if (chars.head == '(')
          checkParentesys(chars.tail, '(' :: parentesis)
        else if (chars.isEmpty || parentesis.isEmpty)
          false
        else
          checkParentesys(chars.tail, parentesis.tail)
    
      checkParentesys(chars.filter(Set('(', ')')), List())
    }
    

    You could also just turn the whole thing into a pattern match:

    def balance(chars: List[Char]): Boolean = {
      @tailrec
      def checkParentesys(chars: List[Char], parentesis: List[Char]): Boolean =
        (chars, parentesis) match {
          case (Nil, Nil) => true
          case ('(' :: charsTail, _) => checkParentesys(charsTail, '(' :: parentesis)
          case (Nil, _) => false
          case (_, Nil) => false
          case (')' :: charsTail, '(' :: parentesisTail) => checkParentesys(charsTail, parentesisTail)
        }
      checkParentesys(chars.filter(Set('(', ')')), List())
    }
    
    0 讨论(0)
  • 2020-12-08 08:55

    It might be nicer to write it as a fold:

    def balance(chars: List[Char]): Boolean = chars.foldLeft(0){
      case (0, ')') => return false
      case (x, ')') => x - 1
      case (x, '(') => x + 1
      case (x, _  ) => x
    } == 0
    
    0 讨论(0)
  • 2020-12-08 09:05
    var parens :List[Char] =  Nil
    def matcher(chrs: List[Char]): Boolean = {
         if (chrs.isEmpty) {
            return parens.isEmpty
         }
         else {
             chrs.head match {
               case '(' =>  parens = '(' :: parens ;matcher(chrs.tail)
               case ')' =>  if (parens.isEmpty) return false 
                                else if (parens.apply(0) ==  '(') parens = parens.drop(1) 
                                else return false;  
                                matcher(chrs.tail);
               case _ => matcher(chrs.tail)
             }
         }
    }
    

    As you can see I didn't use count because count won't work on ())(

    0 讨论(0)
提交回复
热议问题