List 在方案中相交多个列表

List 在方案中相交多个列表,list,scheme,racket,intersection,List,Scheme,Racket,Intersection,我正在尝试在Scheme中相交更多列表,我需要一些帮助。列表如下所示: (join s1 s2) => (set (set '(?x mike) '(?city chicago)) (set '(?x john) '(?city new-york))) 前两项: (((?x john) (?city new-york)) ((?x mike) (?city chicago)) ((?x mary) (?city london))) 及 我需要查看第一个列表

我正在尝试在Scheme中相交更多列表,我需要一些帮助。列表如下所示:

(join s1 s2)

=> (set (set '(?x mike) '(?city chicago))
        (set '(?x john) '(?city new-york)))
前两项:

(((?x john) (?city new-york))  
 ((?x mike) (?city chicago))  
 ((?x mary) (?city london)))

我需要查看第一个列表中的每个列表(例如A),并查看第二个列表中是否有一个列表(例如B),以便A至少有一个与B相同的元素。如果没有此类元素,则生成的列表将不包含A。上述两个列表的结果将是:

(((?x john) (?city new-york))  
 ((?x mike) (?city chicago)))
由于列表
((?x mary)(?city london))
((?city chicago)(?city new york))中的任何列表都没有共同之处

现在,结果列表必须与下一个列表相交:

(((?x mike) (?game tennis))  
 ((?x john) (?game air-hockey)))
结果列表中的第一个列表,
((?x john)(?city new york))
将与
(?x john)(?game air hockey))具有相同的
(?x john)(?city new york)(?game air hockey))
,因此在我的新结果列表中,第一个列表将如下所示:
(?x john)(?city new york)(?game air hockey))
。按照第二个列表的模式,我将得到
(?x mike)(?芝加哥城市)(?网球比赛))
,我的新结果列表将是:

(((?x john) (?city new-york) (?game air-hockey))  
 ((?x mike) (?city chicago) (?game tennis)))
这意味着,对于至少有一个共同元素的每两个列表,我必须重新组合并将其添加到新的结果列表中


现在我的问题是,你能帮我在Scheme中实现这个吗?我不需要代码,只需要一些关于我应该使用哪些函数的想法:)。

我将从改进你的描述开始
(?x john)
不是
列表
而是
查询
。而
(?x约翰)(?纽约市))
不是一个列表,而是一个
命题。及

不是列表列表,而是命题集

一旦开始明确描述事物,就可以开始定义实体上的某些操作:

query_match
query_has_variable
proposition_has_query
proposition_extend
etc

我知道你必须用列表来解决这个问题,我不会写一个列表实现,因为它会很麻烦(它不是这个工作的最佳数据结构),相反,我将向你展示如何用Racket的set操作来解决这个问题,这样你就可以将它转换为使用列表了。首先,数据的表示:

(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

例如:

(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))
现在很容易编写一个过程,将一组数据中的所有元素与另一组数据重复匹配:

(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))))))
例如,
s1
s2
(如上所述)之间的第一个匹配如下:

(join s1 s2)

=> (set (set '(?x mike) '(?city chicago))
        (set '(?x john) '(?city new-york)))
要在多组数据中找到连续的匹配项,只需根据需要多次调用
join
,每次调用一组数据,累积结果:

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

正如您所看到的,最终结果是我们所期望的。

谢谢您的回答。我想我必须为并集和交集编写自己的函数,但这似乎并不难。我还假设SETFIRST和SETREST对于car和cdr是等价的,没错。不过,算法是一样的——这才是最重要的。干杯
(join s1 s2)

=> (set (set '(?x mike) '(?city chicago))
        (set '(?x john) '(?city new-york)))
(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)))