我需要在Scala中实现自己的List类。我已经实施了:
trait List[+A] {
/** The first element */
def head: A
/** The rest of the elements */
def tail: List[A]
def map[B](f: A => B): List[B]
def flatMap[B](f: A => List[B]): List[B]
def filter(f: A => Boolean): List[A]
// Concatenate two lists
def concat[B >: A](that: List[B]): List[B] = this match {
case Empty => that
case NonEmpty(head, tail) => NonEmpty(head, tail concat that)
}
}
/** The empty list, also known as Nil */
case object Empty extends List[Nothing] {
def head = throw new UnsupportedOperationException("Empty.head")
def tail = throw new UnsupportedOperationException("Empty.tail")
def map[B](f: Nothing => B): List[B] = Empty
def flatMap[B](f: Nothing => List[B]): List[B] = Empty
def filter(f: Nothing => Boolean): List[Nothing] = Empty
override def toString = "Empty"
}
现在我需要实现filter,flatMap和Map方法:
case class NonEmpty[A](head: A, tail: List[A]) extends List[A] {
//def map[B](f: A => B): List[B] = ???
//def flatMap[B](f: A => List[B]): List[B] = ???
def filter(predicate: A => Boolean): List[A] = {
}
例如方法filter(predicate: A => Boolean): List[A]
如何遍历此列表中的每个元素?如何检查给定的谓词是真还是假? (试过if(predicate(head))
- 由于某种原因不起作用。)
谢谢你的帮助。
答案 0 :(得分:3)
您需要使用head
和tail
遍历元素:
def filter(f: A => Boolean): List[A] = {
def loop(xs: List[A], ys: List[A]): List[A] =
if (xs == Empty) ys else loop(xs.tail, if (f(xs.head)) NonEmpty(xs.head, ys) else ys)
loop(this, Empty).reverse
}
可以在List
中定义此实现。您需要的最后一件事是reverse
方法。您可以像filter
一样实现它 - 使用内部方法遍历所有元素。
而不是reverse
,您可以使用非尾递归实现,它不能反转并且可以在子类中实现:
def filter(f: A => Boolean): List[A] =
if (f(head)) NonEmpty(head, tail filter f)
else tail filter f
其他方法可以用类似的方式定义。
答案 1 :(得分:1)
通常情况下,当你住在Fairyland 并且假装(几乎)一切都已经有效时,递归会变得更容易。
假设过滤器已经按照您的要求进行了操作,您将如何使用过滤器使其适用于另一个元素?
好吧,您可以决定是否要包含列表的第一个元素(取决于f
),并让过滤器“已经有效”处理其余部分。然后只是连接列表。
def filter(f: A => Boolean) : List[A] = {
if (f(head)) NonEmpty(head, tail.filter(f))
else tail.filter(f)
}