【问题标题】:How to take intersection of pairs from two lists in scheme?如何从方案中的两个列表中获取对的交集?
【发布时间】:2013-08-08 15:08:41
【问题描述】:

我正在使用 The little schemer 中的这个脚本来获取两组的交集。但我在“成员?”处收到未绑定标识符错误,谁能告诉它有什么问题:

(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)))))

我在上面错过了这个功能:

(define member?
  (lambda (a lat)
    (cond ((null? lat) #f)
          (else (or (eq? (car lat) a)
                    (member? a (cdr lat)))))))

另外,我想将两个列表相交,例如:'((1 2)(2 7))'((1 3)(4 5)) = '((1 5)),关于如何去的任何建议关于它?我正在从这篇文章中寻找答案:How to write a scheme function that takes two lists and returns four lists

【问题讨论】:

  • 不清楚这两个列表如何“相交”以产生'((1 5))
  • 我正在考虑将第一个列表中每对的第一个元素与第二个列表中每对的第一个元素进行比较,然后在匹配发生时添加它们的第二个元素。 ://
  • 您确信这种行为。 (1 5) 既不在第一个也不在第二个列表中.. (intersect '((1 2)(3 4)(5 6)) '((9 10) (7 8) (5 6))) ==> ((5 6)) 是正确理解交集和您的程序的行为。你的member? 只需要使用equal? 而不是eq? 就可以了。
  • 是的。我需要为列表中具有相同第一个元素的对添加 sec 元素,并相应地生成一个输出列表。
  • 注意:该函数存在于列表SRFI库中:docs.racket-lang.org/srfi-std/srfi-1.html#lset-intersection。对于生产质量的集合交集,您可能希望使用专用集合数据类型而不是列表。 docs.racket-lang.org/reference/…

标签: list scheme racket intersection set


【解决方案1】:

您在intersect 中有错字,您已将 1 转换为小写 L。如果您修复了这个问题,如果您比较符号,我觉得您的 intersect 似乎没问题。例如。

(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) 

要让它比较符号以外的其他事物,您需要更改您的member?,使其使用equal? 而不是eq?。会是这样的:

(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))

即使在这之后。上面的符号版本仍然有效。 在任何 LISP(至少是 Common Lisp 和 Scheme)中,您都有 member。它使用equal 并在未找到它时评估为false(无论实现中为假),如果找到它,则从找到元素的位置开始评估参数列表的其余部分(这被认为是真的):

(member 'a '(x y a c)) ; ==> (a c)

使用标准成员而不是您自己的谓词:

(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) 

编辑 1

看来您搜索的不是intersection,而是一个特殊的alist 合并:

#!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))

【讨论】:

  • 这会检查确切的对。 :/我需要检查对的第一个元素,如果为真,则添加第二个元素。谢谢。
  • @user2662909 那是不是的交集。我添加了一个通用的 alist-merge 和一个 alist-merge-add 来满足你的需求。
【解决方案2】:

我的路口解决方案:

#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))]))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-29
    相关资源
    最近更新 更多