我正在继续学习Racket(在这种情况下,是函数式编程)。
此刻我有以下代码:
#lang racket
(define EGS0
(lambda (PSET NSET CSET HSET)
(map (lambda (h)
(cond
[(not (andmap (lambda (p) (my-function h p)) PSET)) h]
[(not (ormap (lambda (n) (my-function h n)) NSET)) h]
) HSET))))
我没有从HSET
列表中删除元素,而是使用不需要删除的元素创建了一个新元素。这段代码只是第一近似:在某些情况下,它会加两次h
,但这不是我的问题。
CSET
是一个空列表,my-function
返回#t
或#f
。
我的问题来自最后一条声明:
然后从HSET中删除H并将H添加到CSET。
有了map
,我可以得到一个列表,但是我不知道如何得到两个列表。我能想到的唯一方法是使用set!
,但如果使用它,它将不会成为功能程序。
我考虑使用for
循环,而不是map,或者做两个循环。
如何获取两个列表(包含HSET元素和CSET列表的新列表)?
更新:
我正在添加一些数据来测试算法(有人需要额外的帮助来了解伪代码)。
(define my-function (lambda (x y) (and x y)))
(define hset '(1))
(define pset '(0))
(define nset '(1))
(egs pset nset '() hset)
它必须返回:'(() (1))
。
答案 0 :(得分:1)
请注意,此问题本质上是程序性的,以函数式风格编写并不那么简单;在这种情况下,编写显式循环比使用map
或filter
更自然。
返回两个值很容易,可以通过在递归中传递两个累加器参数并将其在列表内的末尾返回来进行管理。这是我的实现:
(define (egs pset nset cset hset)
(let loop ((input hset) (output '()) (cset cset))
(if (null? input)
; return modified cset and hset
(list cset output)
(let ((pset-match
(andmap (lambda (p) (my-function (car input) p)) pset))
(nset-match
(ormap (lambda (n) (my-function (car input) n)) nset)))
(cond ((not nset-match)
; if h does not match any members from nset
; remove h from hset, add h to cset
(loop (cdr input) output (cons (car input) cset)))
((not pset-match)
; if h does not match all members of pset
; remove h from hset, leave cset unmodified
(loop (cdr input) output cset))
(else
; otherwise don't remove h from hset, leave cset unmodified
(loop (cdr input) (cons (car input) output) cset)))))))
它与示例输入一起工作:
(define my-function (lambda (x y) (and x y)))
(define hset '(1))
(define pset '(0))
(define nset '(1))
(egs pset nset '() hset)
=> '(() (1))