[英]functional programming with scala
I've been trying to enhance my knowledge with scala. 我一直在尝试通过scala增强我的知识。 I am trying to implement this function recursively but having difficulty. 我试图递归地实现此功能,但有困难。
My main question IS, how can you accept a list in the parameter that accepts either a list or numbers. 我的主要问题是,如何在接受列表或数字的参数中接受列表。
depth(x: Any): Int
is the signature you want, then pattern match on x
to determine if it's a List[_]
or not, where _
indicates you don't care what's in the list. depth(x: Any): Int
是所需的签名,然后在x
进行模式匹配以确定它是否为List[_]
,其中_
表示您不在乎列表中的内容。 (Using Seq[_]
would be the more idiomatic Scala type to use, actually.) Note that the example shown is missing a pair of parens, List(1, 2, List(3))...
It also assumes that depth(8) == 0
(for example). (实际上,使用Seq[_]
将是更惯用的Scala类型。)请注意,所显示的示例缺少一对括号,即List(1, 2, List(3))...
它还假定了depth(8) == 0
(例如)。
A tricky part is that you shouldn't assume that a nested list will either be the first or last element in the "parent" list, ie, ...List(1,List(2,3),4)...
is possible. 一个棘手的部分是,您不应假设嵌套列表将成为“父”列表中的第一个元素或最后一个元素,即...List(1,List(2,3),4)...
是可能的。
A final bit worth mentioning; 最后一点值得一提; if you were building a "production" depth
method, it would be worth having a Tree
abstraction with Node
and Leaf
concrete types so you can use a better type signature, depth(tree: Tree[_]): Int
, to make it explicitly clear when something represents part of the tree structure vs. data in the tree. 如果您要构建“生产” depth
方法,则值得使用Node
和Leaf
具体类型的Tree
抽象,以便可以使用更好的类型签名depth(tree: Tree[_]): Int
明确地使其实现当某些东西代表树结构的一部分与树中的数据时,请清除。 Using List
here is convenient for the exercise, but a bit ambiguous otherwise, since you could have a tree of stuff where some nodes are actually lists. 在这里使用List
对于练习很方便,但是在其他地方有点模棱两可,因为您可能拥有一棵树,其中有些节点实际上是列表。
I will try to answer this by giving a shot on the recursive solution: 我将尝试通过递归解决方案来回答这个问题:
def depth(listOrNum: Any): Int = {
def help(y: Any, c: Int): Int = {
y match {
case y: Int => c
case List(curHead, rest @ _*) =>
Math.max(help(curHead, c+1), help(rest, c))
case _ => 0
}
}
help(listOrNum, 0)
}
collect
is handy here: collect
在这里很方便:
def depth(xs: List[Any]): Int =
1 + xs.collect{case xs: List[_] => depth(xs)}
.foldLeft(0)(_ max _)
PS I agree with Dean's comments about the type List[Any]
being a poor way to represent trees. PS我同意Dean关于List[Any]
类型表示树的糟糕方法的评论。 List[Any]
is a type that should never appear in ordinary Scala code, so I'm sad to see it used in an exercise intended for beginners. List[Any]
是不应该出现在普通Scala代码类型,所以我很伤心看到它在供初学者练习使用。
If you are insisting on using for comprehension, I can provide implementation that works with it. 如果您坚持使用理解力,我可以提供与其配合使用的实现。
First you define two useful classes 首先,您定义两个有用的类
import scala.collection.generic.CanBuildFrom
import scala.collection.mutable.Builder
class Folder[T](init : T, step : (T,T) => T) extends Builder[T,T] {
private[this] var state = init
override def += (elem : T) = {
state = step(state, elem)
this
}
override def clear() {
state = init
}
override def result() : T = state
}
class CanBuildFolder[F,T](init : T, step : (T,T) => T) extends CanBuildFrom[F,T,T] {
override def apply() : Builder[T,T] = new Folder(init, step)
override def apply(from : F) : Builder[T,T] = new Folder(init, step)
}
than you can use them with the for comprehension 而不是可以将它们与一起使用
import scala.math.max
object Test {
val example = List(1, List(2, 3), List( List(4, 5), 6, List(7, List(List(8), 9))))
implicit val maxFolder = new CanBuildFolder[List[Any], Int](0, max)
def depth(source : List[Any]) : Int =
for (x <- source) yield x match {
case l : List[Any] => depth(l) + 1
case _ => 1
}
assert(depth(example) == 5)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.