【问题标题】:Scheme, Check if anything in two lists are the same方案,检查两个列表中的任何内容是否相同
【发布时间】:2013-05-17 13:49:56
【问题描述】:

是否可以检查两个列表是否相同?

(check-list '(嘿饼干猴子)'(苹果披萨饼干) ==> #t

我尝试了类似的东西

(define (check-list list element)
  (let ((x list))
  (cond ((null? x) #f)
        ((eq? (car x) (car element)) #t)
        (else (check-list (cdr x) element))))
  (check-list list (cdr element)))

我知道这写得不正确,但不知道如何解决这个问题。

谁能帮帮我?

【问题讨论】:

    标签: list scheme procedure


    【解决方案1】:

    您可以使用memq 检查第一个列表中的第一个元素是否在第二个列表中,如果不是,则递归检查第一个列表的其余部分是否在第二个列表中:

    (define (check-list list1 list2)
      (cond ((null? list1) #f)
            ((memq (car list1) list2) #t)
            (else (check-list (cdr list1) list2))))
    

    【讨论】:

      【解决方案2】:

      有时,用您的自然语言制定解决问题的过程会有所帮助。让我们稍微简化一下问题。

      如何检查 one 元素是否包含在列表中?做到这一点的一种方法是将一个元素与列表中的每个元素进行比较,直到找到它 - 沿着你已经完成的路线的某个地方 - 但不完全是。快速草稿是:

      (define (member? e lst)
        (cond ((null? lst) #f)       ; empty list doesn't contain e
              (or (eq? e <??>)       ; either the first element is e or
                  (member? e <??>))) ; the rest of the list contains e
      

      我们可以利用之前的知识来解决手头的实际问题。我们知道如何在列表中搜索 one 元素,现在我们需要在另一个列表中搜索列表中的每个元素。

      (define (check-list lst1 lst2)
        (if (or (null? lst1) (null? lst2)) #f  ; empty list(s) share no elements
            (or (member? <??> <??>)            ; first element of lst1 in lst2?
                (member? <??> <??>))))         ; rest of lst1 in lst2?
      

      &lt;??&gt; 应替换为适当的表达式以选择列表的各个部分。

      【讨论】:

      • +1 解释得很好,从教学的角度来看很有价值
      【解决方案3】:

      似乎有点混乱。这里的“大”问题是如何确定两个列表是否共享至少一个共同元素,让我们为此编写一个名为element-in-common? 的过程。在解决这个问题之前,我们需要确定一个 single 元素是否属于一个列表,这就是 check-list 应该做的(请注意,在您的代码中 check-list 作为第二个参数接收一个 元素,但您将其视为元素的列表)。

      您不必编写check-list 过程,它已经存在并且称为member。有了这些知识,我们就可以解决大问题了——如何确定一个列表中的至少一个元素(我们称之为lst1)是否在另一个列表中(称为lst2)?

      简单:我们使用递归遍历lst1 中的每个元素,询问每个元素是否属于lst2。如果lst1 中只有一个元素是lst2 的成员,我们返回#t。如果lst1 中的任何元素都不在lst2 中,我们返回#f。像这样的:

      (define (element-in-common? lst1 lst2)
        (cond (<???>               ; is the first list empty?
               <???>)              ; then there are no elements in common
              ((member <???> lst2) ; is the current element of `lst1` in `lst2`?
               <???>)              ; then there IS an element in common
              (else                ; otherwise
               (element-in-common? <???> lst2)))) ; advance recursion
      

      别忘了测试你的代码:

      (element-in-common? '(hey cookie monkey) '(apple pizza cookie))
      => #t
      
      (element-in-common? '(hey cookie monkey) '(apple pizza pie))
      => #f
      

      【讨论】:

      • 你知道如何检查列表中某个位置是否存在一对吗?检查对? '(苹果派)'(饼干猴苹果派比萨)==> #t |||检查对? '(苹果派) '(苹果饼干猴派披萨) ==> #f
      • @user2409697 没有内置程序,您必须编写一个。这并不难,只需检查当前元素和下一个元素,注意基本情况(空列表,包含单个元素的列表)
      【解决方案4】:

      类似于先前的答案,但利用了逻辑原语:

      (define (intersect? list1 list2)
        (and (not (null? list1))
             (or (member     (car list1) list2)
                 (intersect? (cdr list1) list2))))
      

      【讨论】:

        【解决方案5】:

        这是使用高阶函数的答案

        在 mit-schme 中

        (define (check-list L1 L2)
         (apply boolean/or (map (lambda (x) (member? x L2)) L1)))
        

        【讨论】:

        • 到目前为止,所有解决方案的增长顺序都是指数级的。对于非常大的列表,首先对两个列表进行排序(合并或快速处理列表),然后按顺序比较项目。这是一个更复杂的过程,但在大规模上要快得多。
        【解决方案6】:

        如果列表很长,您可能希望对第一个列表进行哈希处理,然后遍历第二个列表。这将 R5RS 与 srfi-69 一起使用,对于小型列表,您会得到一点开销,但

        (require srfi/69); alist->hash-table, hash-table-ref/default 
        (define (intersect? list1 list2)
          (let ((hash (alist->hash-table (map (lambda (x) (cons x x)) list2) equal? )))
            (let loop ((list list1))
              (and (not (null? list))
                   (or (hash-table-ref/default hash (car list) #f)
                       (loop (cdr list)))))))
        

        【讨论】:

          【解决方案7】:
          (define remove-item
            (lambda (lst ele)
              (if (null? lst)
                  '()
                  (if (equal? (car lst) ele)
                      (remove-item (cdr lst) ele)
                      (cons (car lst)
                            (remove-item (cdr lst) ele))))))
          

          【讨论】:

          • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
          猜你喜欢
          • 1970-01-01
          • 2020-07-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-10
          • 2017-03-25
          • 2012-03-29
          相关资源
          最近更新 更多