如何转换此列表:
List("a", "b", "c", "d")
进入包含以下元素的列表
List(List("a"), List("a", "b"), List("a", "b", "c"), List("a", "b", "c", "d"))
我的要求是从包含目录名称的列表构建相对目录路径列表,其中a
是根目录,b
是a
的叶子,即{{1 }}
示例:
a/b
转换为:
"fruit", "tropical", "mango"
编辑:我可以迭代地执行此操作,但我正在寻找功能性解决方案。
答案 0 :(得分:7)
您可以使用inits
来实现您正在寻找的类似内容:
val xs = List("a", "b", "c", "d")
val ys = xs.inits.toList.reverse.drop(1)
说明:
xs.inits.toList
会给你这个结果:
List(List(a, b, c, d), List(a, b, c), List(a, b), List(a), List())
现在你可以反转它并删除第一个元素并得到它:
List(List(a), List(a, b), List(a, b, c), List(a, b, c, d))
然后,只需输入String
个结果:
ys.map(_.mkString("/")) // results in List(a, a/b, a/b/c, a/b/c/d)
答案 1 :(得分:1)
我认为你应该使用inits
(我会避免依赖返回元素的顺序,尽管记录了最后一个元素是空元素):
val basket = List("fruit", "tropical", "mango")
basket.inits.toList filterNot (_.isEmpty) sortBy (_.length) map (_ mkString "/")
但是,如果您想要一种不使用该库函数的方法,您可以使用自己的递归函数:
def paths(elems: List[String]): List[List[String]] = {
elems match {
case Nil => Nil
case e :: es => List(e) :: (paths(es) map (e :: _))
}
}
paths(basket) map (_ mkString "/")
这不是尾递归的,所以如果你的路径很多元素,它将会破坏堆栈。您可以使用累积参数使其尾递归(实际上,我可以做的最好的是两个累积参数):
@annotation.tailrec
final def paths(elems: List[String], path: List[String], acc: List[List[String]]): List[List[String]] = {
elems match {
case Nil => acc
case e :: es => paths(es, path :+ e, acc :+ (path :+ e))
}
}
paths(basket, Nil, Nil) map (_ mkString "/")
此解决方案虽然在:+
上使用了List
运算符(追加元素),但它在时间复杂度方面并不是最优的。我将把它作为读者的练习(提示:您可能希望以相反的顺序存储累积参数)。