Racket中将函数列表应用到字符串列表的实现难题
嘿,作为Racket/Scheme新手,刚接触这种嵌套遍历的需求确实容易卡壳——我当初学的时候也在递归处理列表上绕了好久,不过别担心,咱们用最基础的Scheme递归就能搞定,完全不用集合类!
核心思路拆解
你的需求本质是两层嵌套遍历:
- 先逐个取出函数列表里的每个函数
- 对每个函数,再逐个作用于字符串列表里的所有字符串
- 把每一步的结果按顺序收集到最终列表里
Scheme里处理列表的核心就是递归,咱们把大问题拆成小问题:先写一个辅助函数处理「单个函数作用于所有字符串」,再写主函数遍历所有函数,把每个函数的处理结果拼接起来。
代码实现步骤
1. 辅助函数:单个函数处理整个字符串列表
先写一个apply-function-to-strings函数,它接受一个函数f和字符串列表s,返回f作用于每个字符串后的结果列表:
(define (apply-function-to-strings f s) (if (null? s) ; 如果字符串列表为空,返回空列表 '() ; 把f作用于第一个字符串,再和递归处理剩下字符串的结果拼接 (cons (f (car s)) (apply-function-to-strings f (cdr s)))))
举个例子,要是f是转大写函数,s是("a" "b"),调用这个函数就会返回("A" "B")。
2. 主函数:遍历所有函数并拼接结果
接下来写主函数apply-all-functions,它接受函数列表funcs和字符串列表strs,把每个函数的处理结果依次拼接:
(define (apply-all-functions funcs strs) (if (null? funcs) ; 如果函数列表为空,返回空列表 '() ; 把第一个函数的处理结果,和递归处理剩下函数的结果拼接 (append (apply-function-to-strings (car funcs) strs) (apply-all-functions (cdr funcs) strs))))
这里用append而不是cons,因为每个函数处理后得到的是一个列表,我们需要把多个列表连起来,而cons是用来给列表加单个元素的。
测试验证
咱们用你举的例子来测试一下:
; 定义测试用的函数 (define (f1 s) (string-upcase s)) ; 转大写 (define (f2 s) (string-append "pre-" s)) ; 加前缀"pre-" ; 定义你的函数列表和字符串列表 (define funcs (list f1 f2)) (define strs (list "a" "b" "c")) ; 调用主函数 (apply-all-functions funcs strs)
运行后会得到结果:'("A" "B" "C" "pre-a" "pre-b" "pre-c"),完全符合你要的顺序!
额外说明
整个实现只用了Scheme最基础的列表操作:null?判断空列表、car取第一个元素、cdr取剩下的列表、cons拼接元素与列表、append拼接两个列表,完全没用到任何集合类,完美满足你的要求。
刚开始写递归可能会觉得抽象,你可以手动走一遍递归的步骤:比如处理(list f1 f2)时,先处理f1得到("A" "B" "C"),再处理f2得到("pre-a" "pre-b" "pre-c"),最后用append把这两个列表连起来就是最终结果啦。
内容的提问来源于stack exchange,提问作者William Jones

