且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

与Scheme中的更多列表相交

更新时间:2023-11-29 19:25:10

我知道您必须使用列表来解决此问题,我不会编写列表实现,因为这样做会很麻烦(这不是适用于的***数据结构作业),我将向您展示如何通过Racket的设置操作解决问题,以便您可以将其转换为使用列表.首先,数据的表示形式:

I understand that you have to solve this with lists, I won't write a list implementation because it'd be cumbersome (it's not the best data structure for the job), instead I'll show you how to solve the problem in terms of Racket's set operations, so you can translate it to use lists. First, a representation of the data:

(define s1 (set (set '(?x john) '(?city new-york))
                (set '(?x mike) '(?city chicago))
                (set '(?x mary) '(?city london))))

(define s2 (set (set '(?city chicago))
                (set '(?city new-york))))

(define s3 (set (set '(?x mike) '(?game tennis))
                (set '(?x john) '(?game air-hockey))))

使用表示形式后,我们需要一个过程,给定单个基准,查找是否与某个数据列表共享某些元素-如果找到一个匹配项,则返回数据的并集;如果不存在,则返回数据的并集.找到返回#f的任何内容:

With the representation in place, we need a procedure that given a single datum finds if it shares some element in common with a list of data - if it finds one match, it returns the union of data, if it doesn't find any it returns #f:

(define (find-match one-set set-of-sets)
  (cond ((set-empty? set-of-sets)
         #f)
        ((not (set-empty? (set-intersect one-set (set-first set-of-sets))))
         (set-union one-set (set-first set-of-sets)))
        (else
         (find-match one-set (set-rest set-of-sets)))))

例如:

(find-match (set '(?x mike) '(?city chicago))
            (set (set '(?x mike) '(?game tennis))
                 (set '(?x john) '(?game air-hockey))))

=> (set '(?x mike) '(?city chicago) '(?game tennis))

现在很容易编写一个将一组数据中的所有元素与另一组数据重复匹配的过程:

Now it's easy to write a procedure that repeatedly matches all elements in one set of data with another set of data:

(define (join s1 s2)
  (let loop ((s1 s1)
             (result (set)))
    (if (set-empty? s1)
        result
        (let ((match (find-match (set-first s1) s2)))
          (if match
              (loop (set-rest s1) (set-add result match))
              (loop (set-rest s1) result))))))

例如,s1s2(如上定义)之间的第一个匹配如下所示:

For instance, the first match between s1 and s2 (as defined above) would look like this:

(join s1 s2)

=> (set (set '(?x mike) '(?city chicago))
        (set '(?x john) '(?city new-york)))

要在几组数据中查找连续的匹配项,只需根据需要多次调用join,每组数据都会累加结果:

To find successive matches among several sets of data just call join as many times as needed, with each set of data, accumulating the result:

(define (join-all . data)
  (if (empty? data)
      (set)
      (foldr join (first data) (rest data))))

(join-all s1 s2 s3) ; equivalent to (join (join s1 s2) s3)

=> (set
     (set '(?x john) '(?city new-york) '(?game air-hockey))
     (set '(?x mike) '(?city chicago)  '(?game tennis)))

如您所见,最终结果是我们预期的结果.

As you can see, the end result is the one we expected.