问题
I am using this script from The little schemer, to get intersection of two sets. But I am getting unbound identifier error at 'member?', can anyone please tell what's wrong with it:
(define intersect
(lambda (set1 set2)
(cond ((null? set1) (quote ()))
((member? (car set1) set2)
(cons (car setl)
(intersect (cdr set1) set2)))
(else (intersect (cdr setl) set2)))))
I was missing this function above:
(define member?
(lambda (a lat)
(cond ((null? lat) #f)
(else (or (eq? (car lat) a)
(member? a (cdr lat)))))))
Also, I want to intersect two lists like: '((1 2)(2 7)) '((1 3)(4 5)) = '((1 5)), any suggestions on how to go about it? I am looking up the answers from this post: How to write a scheme function that takes two lists and returns four lists
回答1:
You have a typo in intersect
where you have switched 1 with as lower case L. If you fix that your intersect
seems fine by me if you are comparing symbols. Eg.
(define intersect
(lambda (set1 set2)
(cond
((null? set1)(quote ()))
((member? (car set1) set2)
(cons (car set1)
(intersect (cdr set1) set2)))
(else (intersect (cdr set1) set2)))))
(intersect '(a b c d) '(c d e f)) ; ==> (c d)
To make it compare other things than symbols, you need to change your member?
so that it uses equal?
instead of eq?
. It will be like this:
(define member?
(lambda (a lat)
(cond
((null? lat) #f)
(else (or (equal? (car lat) a) ; changed eq? to equal?
(member? a (cdr lat)))))))
(intersect '((1 2)(3 4)(5 6)) '((9 10) (7 8) (5 6))) ; ==> ((5 6))
Even after this. The symbol version above still works.
In any LISP (Common Lisp and Scheme at least) you have member
. It uses equal
and evaluate to false
(whatever is false in the implementation) when it's not found and if it's found it evaluates to the rest of the argument list starting from where the element was found (which is considered true):
(member 'a '(x y a c)) ; ==> (a c)
Using standard member instead of your own predicate:
(define intersect
(lambda (set1 set2)
(cond
((null? set1)(quote ()))
((member (car set1) set2)
(cons (car set1)
(intersect (cdr set1) set2)))
(else (intersect (cdr set1) set2)))))
(intersect '((1 2)(3 4)(5 6)) '((9 10) (7 8) (5 6))) ; ==> ((5 6))
(intersect '(a b c d) '(c d e f)) ; ==> (c d)
EDIT 1
It seems you are not searching for intersection
but a special alist
merge:
#!r6rs
(import (rnrs base)
(rnrs lists))
;; if you dont have r6rs remove the above and
;; uncomment this rnrs/lists-6 memp
#;(define (memp predicate? lst)
(cond ((null? lst) #f)
((predicate? lst) lst)
(else (memp predicate? (cdr lst)))))
(define (alist-merge merge-proc alist-1 alist-2)
(if (null? alist-1)
'()
(let* ((name (caar alist-1))
(found (memp (lambda (x) (equal? (car x) name)) alist-2)))
(if found
(cons (merge-proc (car alist-1) (car found))
(alist-merge merge-proc
(cdr alist-1)
alist-2))
(alist-merge merge-proc
(cdr alist-1)
alist-2)))))
(define (alist-merge-add alist-1 alist-2)
(alist-merge (lambda (x y)
(list (car x)
(+ (cadr x) (cadr y))))
alist-1
alist-2))
(alist-merge-add '((1 2)(2 7)) '((1 3)(4 5))) ; ==> ((1 5))
回答2:
My intersection solution:
#lang racket
(define (intersect set1 set2)
(cond [(empty? set1) '()]
[(empty? set2) '()]
[(= (caar set1) (caar set2)) (cons (list (caar set1)
(+ (cadar set1)
(cadar set2)))
(intersect (cdr set1) (cdr set2)))]
[(< (caar set1) (caar set2)) (intersect (cdr set1) set2)]
[else (intersect set1 (cdr set2))]))
来源:https://stackoverflow.com/questions/18129617/how-to-take-intersection-of-pairs-from-two-lists-in-scheme