我在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的新手,我必须忽视某些事情 - 有人可以指出它可能是什么吗?
答案 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)
}