Racket中不使用indexes-of筛选列表元素索引的问题
手动实现Racket中符合条件元素的索引收集(禁用
indexes-of) 问题根源
你原代码的核心问题在于Racket的变量是不可变的:append会生成新列表,但你没有将这个新列表重新绑定到output上,循环过程中output始终保持初始的空列表状态,最后自然返回空。
修复方案:用for/fold累积结果
Racket提供了for/fold专门用于循环中构建累积值,结合in-indexed可以同时遍历元素和索引,完美解决你的需求。这里提供两种实现:
基础实现(直观但效率一般)
(define (filter-indexes lst condition) (for/fold ([output empty]) ([(elem idx) (in-indexed lst)]) (if (condition elem) (append output (list idx)) ;; 每次在列表末尾添加索引 output)))
高效实现(推荐)
append每次都要遍历整个已有列表,效率较低。可以先用cons把索引加到列表头部,最后反转得到正确顺序:
(define (filter-indexes lst condition) (reverse (for/fold ([output empty]) ([(elem idx) (in-indexed lst)]) (if (condition elem) (cons idx output) ;; O(1)操作,加到列表头部 output))))
代码说明
in-indexed:将输入列表转换为元素+索引的配对序列,避免手动计算索引的麻烦for/fold:第一个参数是累积值的初始状态(这里是空列表),每次循环根据条件更新累积值- 不可变变量的思考:Racket中不要试图“修改”变量,而是通过每次生成新值并传递的方式构建结果,这是函数式编程的核心思想
示例使用
比如要收集所有偶数的索引:
(filter-indexes '(1 2 3 4 5) even?) ;; 返回 '(1 3)
内容的提问来源于stack exchange,提问作者JaySay
相关产品推荐
相关产品推荐

