MIT-Scheme中如何按索引过滤?以P16习题为例求函数式实现
在MIT-Scheme中实现按索引过滤(删除第N个元素)的函数式方法
要实现类似你Python示例中的按索引过滤逻辑,MIT-Scheme没有内置的enumerate函数,但可以通过构造带索引的元素对,结合filter和map来实现,或者用fold(折叠)来更简洁地处理索引逻辑。以下是几种方案:
1. 模拟enumerate + 过滤映射
先实现一个简单的enumerate函数,生成(索引 . 元素)的配对列表,再过滤掉符合删除条件的配对,最后提取元素:
; 生成带索引的元素对列表,索引从0开始 (define (enumerate lst) (let loop ([lst lst] [idx 0]) (if (null? lst) '() (cons (cons idx (car lst)) (loop (cdr lst) (+ idx 1)))))) ; 定义删除第N个元素的函数 (define (drop-every-nth lst n) (map cdr (filter (lambda (pair) ; 过滤掉位置(索引+1)能被n整除的元素 (not (zero? (modulo (+ (car pair) 1) n)))) (enumerate lst)))) ; 测试 (display (drop-every-nth '(a b c d e f g h i j k) 3)) ; => (a b d e g h j k)
2. 用fold-left实现更简洁的版本
利用fold-left(MIT-Scheme内置)来遍历列表,同时跟踪当前元素的位置,避免显式递归:
(define (drop-every-nth lst n) (reverse (fold-left (lambda (acc elem) ; 累加器acc是反向的结果,当前元素的位置是累加器长度+1(从1开始计数) (let ([pos (+ (length acc) 1)]) (if (zero? (modulo pos n)) acc ; 跳过第n个元素 (cons elem acc)))) ; 保留元素,加入累加器 '() lst))) ; 测试 (display (drop-every-nth '(a b c d e f g h i j k) 3)) ; => (a b d e g h j k)
3. 紧凑的匿名函数写法
如果不想单独定义enumerate,可以把索引生成逻辑直接整合到过滤过程中:
(display (map cdr (filter (lambda (pair) (not (zero? (modulo (+ (car pair) 1) 3)))) (let loop ([lst '(a b c d e f g h i j k)] [idx 0]) (if (null? lst) '() (cons (cons idx (car lst)) (loop (cdr lst) (+ idx 1)))))))) ; => (a b d e g h j k)
这些方法都符合函数式编程的风格,避免了可变状态,和你Python中用enumerate+filter/列表推导式的思路一致。
内容的提问来源于stack exchange,提问作者Dinay Kingkiller
相关产品推荐
相关产品推荐

