Functional programming 使用地图获取两个不同的列表

Functional programming 使用地图获取两个不同的列表,functional-programming,scheme,racket,Functional Programming,Scheme,Racket,我正在继续学习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 (l

我正在继续学习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

我的问题来自最后一句话:

然后将H从HSET中移除,并将H添加到CSET中

使用
map
我可以得到一个列表,但我不知道如何得到两个列表。我能想到的唯一方法就是使用
set,但如果我使用它,它将不是功能程序

我想用
来代替map,或者做两个循环

如何获得这两个列表(包含HSET元素的新列表和CSET列表)

更新:
我正在添加一些数据来测试算法(有人需要额外的帮助来理解伪代码)


它必须返回:
”(()(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))

map
不是执行任务的合适工具。您希望允许输出列表可能比输入列表短,但
map
将始终返回相同长度的列表。查看并了解如何利用它。我发现您最近一直在努力使用
map
。通常,当我们已经有一个列表时,我们使用
map
,我们希望创建一个具有相同元素数的新列表,其中每个输出元素都是对输入列表的每个元素应用一个函数的结果。就是这样,不要试图使用
map
来处理所有需要循环的事情。在当前状态下,这个问题是不稳定的。请为
hset
pset
nset
发布一些示例输入,以及
hset
cset
的预期输出。同时发布
my function
的代码。通过示例输入,您更容易理解所需内容。我更新了我的答案。谢谢你的回答:我认为这段代码,
(和(不是pset匹配)(不是nset匹配))
,是错误的(或者可能我没有理解它)。只有当h不匹配NSET的任何成员时,我才必须将h添加到cset。当h不匹配所有PSET和任何NSET时,在代码中添加它。是的,这就是我的代码所做的。因为在伪代码中,他们首先检查h是否与pset的所有成员都不匹配,在这两种情况下,我们都从hsetI中删除了元素。我认为真正的问题是:我们是否将伪代码中的两个if解释为:一个先,另一个后(总是同时执行这两个操作),或者一个先,并且只有在另一个没有成功时才执行(仅当第一个失败时才执行第二个)?可能您必须将递归调用放在
cond
语句之外,并使用两个辅助变量:一个用于带H的HSET是否删除它,另一个用于带H的CSET是否添加H。在我的代码中,我将伪代码解释为“如果始终都执行”,这就是为什么我的测试是
(和(非pset匹配)(非nset匹配))
(define my-function (lambda (x y) (and x y)))

(define hset '(1))
(define pset '(0))
(define nset '(1))

(egs pset nset '() hset)
=> '(() (1))