【问题标题】:Scheme Compare item or list if it's inside the test list (can be nested)Scheme 比较项目或列表是否在测试列表中(可以嵌套)
【发布时间】:2009-09-25 13:33:43
【问题描述】:

我的目标是让函数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

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

【问题讨论】:

    标签: list scheme


    【解决方案1】:

    免责声明:我已经 20 年没有定期编写方案了。

    我认为你想从整个 lispy/schemey 方法的角度来考虑这个问题,即建立你的条件。

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

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

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

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

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

    我会这样写代码

    (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 结构,因为它非常适合这类问题 - 解决问题感觉不错 - 请注意 null 检查。我写的一样吗?作为辅助函数,以防您想自己编写它。您可以通过这种方式轻松实现:

    (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 或者它们都是列表并且汽车相同并且 cdr 相同,则它们是相同的,否则为假。

    你可以同样轻松地重写吗?像这样:

    (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 的概念抽象为一个函数,该函数应用 part 结构规则和由您提供的相等谓词。这使得更改规则变得非常容易。当您点击地图车时,这将更有意义。

    【讨论】:

    • 非常感谢您的帮助!我刚刚发现有一个名为 member 的本机函数可以做非常相似的事情。我只需要将列表变成递归即可。
    • 您可能要小心使用成员 - 通常在早期的作业问题中,您被禁止使用内置插件,以便您习惯于完成所有工作并内化该过程。这就像用手做长除法而不是使用计算器,如果这有意义的话。
    • 您可能需要调整此函数,使其在 item 为 '() 时正常工作。
    【解决方案2】:

    这里使用的= 函数的问题是,它只为数字定义。为了测试任意数据的相等性,有谓词eq?eqv?equal?。这里列出了从最有区别(eq?,基本上类似于指针比较)到最低区别(equal? 将考虑类型和结构)。 eqv? 谓词介于两者之间(对于数字是类型感知的,否则就像 eq? 一样)。

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

    编辑可以在R6RS 中找到有关这些谓词的详细信息。

    【讨论】:

    • 感谢您的点击,我应该使用 eq 吗?我认为。我怎样才能递归地做到这一点?以便嵌套列表也进行比较?
    • 想一想:您实际上可能有两个列表,它们看起来相同,但却是不同的对象。 eq? 会为这些对象返回什么? equal? 会返回什么?
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-03
      • 1970-01-01
      • 2021-09-01
      • 1970-01-01
      相关资源
      最近更新 更多