Scala从列表中删除项目 - 方法比较

时间:2016-03-16 03:06:59

标签: scala

我在Coursera开始学习Scala编程课程,来自2年Java / Python / C#经验。

我正在解决一个问题,你必须检查字符列表是否有平衡的paranthesis。

/**
* Exercise 2
*/
def balance(chars: List[Char]): Boolean = {

def recursiveBalance(chars: List[Char]): Boolean = {
  if (!chars.contains('(') && !chars.contains(')')) true
  else {
    val openIndex = chars.indexOf('(')
    if (openIndex == -1) false
    else {
      val chars2 = dropFirstMatch(chars, '(')
      val closeIndex = chars2.indexOf(')')
      if(closeIndex == -1 || openIndex > closeIndex) false
      else recursiveBalance(dropFirstMatch(chars2, ')'))
    }
  }
}

def remove(index: Int, list: List[Char]): List[Char] = {
  list.take(index) ++ list.drop(index)
}

def dropFirstMatch[A](ls: List[A], value: A): List[A] = {
  val index = ls.indexOf(value)  //index is -1 if there is no match
  if (index < 0) {
    ls
  } else if (index == 0) {
    ls.tail
  } else {
    // splitAt keeps the matching element in the second group
    val (a, b) = ls.splitAt(index)
    a ++ b.tail
  }
}
recursiveBalance(chars)

}

所以这个解决方案正在运行(如果有点难看)。作为解决方案的一部分,我尝试从特定索引处的列表中删除对象。我已经了解到,在Scala中,列表是不可变的。

我尝试这样做是为了提供索引,列表,并使用this example,这是remove函数。这在REPL中工作,我制作了一个列表,运行了该函数,并返回了一个没有指定索引的新列表。

但这在我的balance解决方案中无效。每次返回列表时它都没有变化,导致无限递归。最后我偶然发现了this article并借用了他们的dropFirstMatch函数,并用它取代了bam,工作解决方案。

我是Scala的新手,我必须忽视某些事情 - 有人可以指出它可能是什么吗?

2 个答案:

答案 0 :(得分:3)

take(n)选择列表中的前n个元素,其中drop(n)选择列表中除前n个元素之外的所有元素。

举例说明:

scala> val xs = List(0,1,2,3,4,5)
xs: List[Int] = List(0, 1, 2, 3, 4, 5)

scala> xs.take(2)
res0: List[Int] = List(0, 1)

scala> xs.drop(2)
res1: List[Int] = List(2, 3, 4, 5)

scala> xs.take(2) ++ xs.drop(2)
res2: List[Int] = List(0, 1, 2, 3, 4, 5)

换句话说,您的remove函数只返回相同的列表,因为take是原始列表的前n个元素,然后将其添加到原始列表的元素(第一个除外)其中(drop)。为了删除列表中给定索引处的元素,您只需要在调用drop中将索引增加1:

def remove(index: Int, list: List[Char]): List[Char] = {
  list.take(index) ++ list.drop(index+1)
}

答案 1 :(得分:2)

检查平衡括号比你正在做的更容易:

  def balanced(list: Seq[Char]): Boolean  = list.foldLeft(0) { 
     case (n, _) if (n < 0) => return false
     case (n, '(') => n + 1
     case (n, ')') => n - 1
     case (n, _) => n
  } == 0

或者,如果你是一个纯粹主义者,就像一些评论者,并坚持递归:

  @tailrec
  def balanced(chars: Seq[Char],  n: Int = 0): Boolean = (n, chars) match {
    case (-1, _) => false
    case (n, Nil) => n == 0
    case ('(' :: tail, n) => balanced(tail, n+1)
    case (')' :: tail, n) => balanced(tail, n-1)
    case (_ :: tail, n) => balanced(tail, n)
  }