Scheme比较项目或列表,如果它在测试列表中(可以嵌套)

时间:2009-09-25 13:33:44

标签: list scheme

如果列表或项目在嵌套列表中,我的目标是使函数part?返回true。

但到目前为止,我只能在第一个订单列表中使用信号项。 (尚未嵌套列表)

(define part?  
  (lambda (item l)
    (and (not (null? l))
         (or (= item (car l))
             (part? item (cdr l))))))

我的目标是

部分? (A(B)),(((B)A(B))C)是#f和

部分? (A B),(C(A B)(C))是#t

我应该在哪些方面进行改进?如何使列表与嵌套列表进行比较?

3 个答案:

答案 0 :(得分:2)

免责声明:我没有在20年内定期撰写计划。

我认为你想从整个lispy / schey方法来考虑这个问题,这是为了确定你的条件。

给定一个输入项目,您想要查找列表是否包含该项目。

  1. 如果列表不为空,则列表可能包含项目。

  2. 如果列表中的汽车与项目匹配或者列表中的汽车包含项目,则列表包含项目

  3. 如果列表的cdr包含该项目,则列表包含一个项目。

  4. 要考虑的最后一个问题,(部分?'(a b)'(a b))的结果是什么?

  5. 我会写这样的代码

    (define part? (lambda (item l)
        (cond ((null? l) f)
              ((or (same? item (car l)) (part? item (car l))))
              (t (part? item (cdr l)))
        )
    ))
    
    (define same? (lambda (a b) (eq? a b)))
    

    我使用了cond结构,因为它非常适合这种问题 - 只是将问题排除在外是正确的 - 注意空检查。我写的一样吗?作为帮助函数,以防您想自己编写。你可以这样轻松地做到这一点:

    (define same? (lambda (a b)
        (cond ((and (atom? a) (atom? b)) (eq? a b))
              ((and (list? a) (list? b)) (and (same? (car a) (car b)) (same? (cdr a) (cdr b))))
              (f f)
        )
    ))
    

    基本上说两个项目是相同的,如果它们都是原子而且它们是eq或者它们都是列表而且汽车是相同的而且cdrs是相同的,否则是假的。

    您可以轻松地重写相同的内容吗?这样:

    (define same? (lambda (a b) (equal? a b)))
    

    这样做的关键是代码中存在瓶颈 - 如何确定两个项目是否相同。如果您将该瓶颈分解为自己的功能,则可以使用不同的机制替换它。我知道你还没到,但是你会在某一点上:你也可以重写代码,以便传递谓词。这样的事情(以及更多最新的计划程序员,随意纠正我):

    (define part-pred? (lambda (same-pred item l)
        (cond ((null? l) f)
              ((or (same-pred item (car l)) (part? item (car l))))
              (t (part? item (cdr l)))
        )
    ))
    
    (define part-eq? (lambda (item l) (part-pred? 'eq? item l)))
    (define part-same? (lambda (item l) (part-pred? 'same? item l)))
    (define part-equal? (lambda (item l) (part-equal? 'equal? item l)))
    

    现在已经将part的概念抽象为一个函数,它应用了部分结构规则和由你提供的等式谓词。这使得改变规则变得非常容易。当你点击mapcar时,这会更有意义。

答案 1 :(得分:1)

此处使用的=函数的问题是,它仅针对数字定义。要测试任意数据的相等性,可以使用谓词eq?eqv?equal?。这里列出的最具辨别力(eq?,基本上类似于指针比较)到最不区别(equal?将考虑类型和结构)。 eqv?谓词位于介于两者之间(类型识别数字,否则就像eq?其他任何东西)。

要比较列表,您通常会使用equal?

修改有关这些谓词的详细信息,请参阅R6RS

答案 2 :(得分:1)

您的解决方案缺少这个想法,因为您正在处理嵌套列表,您需要检查每个列表中的每个项目是否都是列表本身,如果是,则检查给定列表是否是另一个或部分列表的一部分列表的其余部分如果没有那么你需要检查第一项是否相等以及给定列表的其余部分是否是另一部分的一部分。

(define part? item l
  (cond (and (list? (car item)) (not (list? (car l))) ...)
        (and (not (list? (car item))) (list? (car l)) ...)
        (and (not (list? (car item))) (not (list? (car l))) ...) 
        (and (list? (car item)) (list? (car l))) ...)