如果列表的第一个元素为零,则尝试删除它的第一个元素(不是真的,但是出于示例的目的)。
给出一个清单:
val ns = List(0, 1, 2)
删除第一个零可以通过将第一个匹配项删除为零来完成:
List(0, 1, 2).dropWhile(_ == 0)
res1: List[Int] = List(1, 2)
或者你可以删除所有不是零的东西。
List(0, 1, 2).filter(_ > 0)
res2: List[Int] = List(1, 2)
这些问题是当列表有多个零时。以前的解决方案不起作用,因为它们删除了太多的零:
List(0, 0, 1, 2, 0).filter(_ > 0)
res3: List[Int] = List(1, 2)
List(0, 0, 1, 2, 0).dropWhile(_ == 0)
res4: List[Int] = List(1, 2, 0)
这是否有现有功能?
答案 0 :(得分:6)
我还认为模式匹配是可读性和性能的最佳选择(我测试过,OP中的模式匹配代码实际上比简单if ... else ...
更好。)。
List(0, 0, 1, 2, 0) match {
case 0 :: xs => xs
case xs => xs
}
res10: List[Int] = List(0, 1, 2, 0)
而且,不,没有简单的内置功能。</ p>
答案 1 :(得分:2)
如果您只想有条件地删除第一个元素,那么正如jwvh评论的那样,if/else
理解可能是最简单的:
if (ns.nonEmpty && ns.head == 0) {
ns.tail
} else {
ns
}
然后你可以把它包装成一个函数。
您可以查找一个零的序列,然后删除它:
if (ns.startsWith(List(0))) {
ns.drop(1)
} else {
ns
}
也称为返回尾巴:
if (ns.startsWith(List(0))) {
ns.tail
} else {
ns
}
答案 2 :(得分:1)
一个简洁的通用解决方案将明确地向您的元素添加信息。
实施例: 如何按条件下降并从左到右限制金额?
List(0,0,0,1,2,2,3).zipWithIndex.dropWhile({case (elem,index) => elem == 0 && index < 2})
结果:
res0: List[(Int, Int)] = List((0,2), (1,3), (2,4), (2,5), (3,6))
您可以通过以下方式获取之前的演示文稿:
res0.map.{_._1}
要在N中执行所有操作,您可以使用延迟评估+ force
方法。
List(0,0,0,1,2,2,3).view.zipWithIndex.dropWhile({case (elem,index) => elem == 0 && index < 2}).map {_._1}.force
这将基本上在一次迭代中对初始集合执行所有操作。有关Scala视图的详细信息,请参阅scaladoc。
在正确的尺寸上修改您的条件,您可以选择放置条件在您的收藏中达到的距离。
答案 3 :(得分:1)
您可以使用索引压缩列表:
ns.zipWithIndex.filter( x =>( x._1 != 0 || x._2 != 0)).map(_._1)
以下是使用dropWhile
的类似解决方案:
ns.zipWithIndex.dropWhile {
case (x, idx) => x == 0 && idx == 0
} map(_._1)
这也可能是一种理解
for {
(x, idx) <- ns.zipWithIndex
if (x != 0 || idx != 0) )
} yield {
x
}
但正如保罗所说,它将不必要地遍历整个列表。
答案 4 :(得分:1)
这是一个广义变体(放到与谓词匹配的K个元素),它不处理列表的其余部分
def dropWhileLimit[A](xs: List[A], f: A => Boolean, k: Int): List[A] = {
if (k <= 0 || xs.isEmpty || !f(xs.head)) xs
else dropWhileLimit(xs.tail, f, k - 1)
}
和一些测试用例:
dropWhileLimit(List(0,1,2,3,4), { x:Int => x == 0}, 1)
//> res0: List[Int] = List(1, 2, 3, 4)
dropWhileLimit(List(0,1,2,3,4), { x:Int => x == 0}, 2)
//> res1: List[Int] = List(1, 2, 3, 4)
dropWhileLimit(List(0,0,0,0,0), { x:Int => x == 0}, 1)
//> res2: List[Int] = List(0, 0, 0, 0)
dropWhileLimit(List(0,0,0,0,0), { x:Int => x == 0}, 3)
//> res3: List[Int] = List(0, 0)