作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在用 .foldRight()
递归地实现高阶函数。喜欢 any
, all
, 和 takeWhile
作为实践,但 dropWhile
一直难以捉摸。 _Collections.kt
具有命令式的方式,但我无法将其转换为递归结构。
作为引用,这是 takeWhile
fun takeWhile(list:List<Int>, func:(Int) -> Boolean):List<Int> = list.foldRight(emptyList(),
{ next:Int, acc:List<Int> -> if (func(next)) acc.plus(next) else emptyList() })
最佳答案
首先,让我们概述解决方案的想法。
使用 foldRight
,您只能从右到左一个一个地处理项目,保持一个累加器。
问题是,对于位置 i
的项目, dropWhile
逻辑根据位置 j <= i
是否存在不满足谓词的项目(如果是,则包括)来决定是否将项目包含到结果中。这意味着您不能简单地维护结果项目:对于您已经处理的某些项目,您不知道它们是否应该实际包含在内。
例子:
(我们从右到左处理项目,所以前缀对我们来说是未知的)
... (some unknown items) ... ... ... ... a b c d <--- (right-to-left)
predicate satisfied: T T F T
F
的项目: (the sequence start) y z a b c d <--- (right-to-left)
predicate satisfied: T T T T F T
-------
drop
y z a b
。 ... (some unknown items) ... w z a b c d <--- (right-to-left)
predicate satisfied: F T T T F T
-------
include
w z a b
,我们不能更早地这样做,因为可能有序列的开头而不是项目 w
,然后我们应该删除 z a b
。 c d
将包含在结果中:这是因为它们前面有
c
和
F
谓词。
false
谓词时将被删除或包含遇到结果,以及给出这种
false
结果的项目。
fun <T> List<T>.myDropWhile(predicate: (T) -> Boolean) =
foldRight(Pair(emptyList<T>(), emptyList<T>())) { item, (certain, uncertain) ->
if (predicate(item))
Pair(certain, uncertain + item) else
Pair(certain + uncertain + item, emptyList())
}.first.reversed()
val ints = listOf(0, 0, 0, 1, 0, 2, 3, 0, 0, 4)
println(ints.myDropWhile { it == 0 }) // [1, 0, 2, 3, 0, 0, 4]
uncertain + item
或
certain + uncertain + item
复制只读列表会给出
O(n^2)
最坏情况时间复杂度,这是不切实际的。使用可变数据结构给
O(n)
时间。
关于recursion - 如何在 Kotlin 中使用 foldRight 递归实现 dropWhile,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46063844/
我是一名优秀的程序员,十分优秀!