Scheme:找出“复杂”元素是否在“复杂”列表中

时间:2012-10-20 16:14:12

标签: list scheme lisp member

我正在使用R5RS标准的Scheme实现。

现在想象你必须找出元素'(2 3 4)是否在列表中(1 2 3 4)。

至于示例,更严格地说,您希望:

1. (is-in? '(2 3 4) '(1 2 3 4)) -> #f
2. (is-in? '(2 3 4) '(1 (2 3 4)) -> #t

问题:如何获得这种行为,如例1所示?

让我解释一下:当您搜索列表时,可以使用carcdr来获取其中的部分。现在,如果你以递归方式遍历列表,最终会得到:

3. (cdr '(1 2 3 4)) -> '(2 3 4)
4. (cdr '(1 (2 3 4)) -> '((2 3 4))

所以最终我们得到了2个名单。你可以在这里看到,子列表'(2 3 4)包含在两个 3和4的结果中。

请注意3和4与1和2的矛盾:'(2 3 4)未包含在'(1 2 3 4)中,cdr的递归调用返回'(2 3 4),其中 等于'(2 3 4) - 并使用相等?函数,在递归调用中的某个地方,我们最终获得1和2的#t:

5. (is-in? '(2 3 4) '(1 2 3 4)) -> #t
6. (is-in? '(2 3 4) '(1 (2 3 4)) -> #t

那么如何从1获得这种行为呢?我想要一个功能,它适用于所有不同类型的数据。这是我的函数,它的作用类似于5和6(通常应该作为1和2):

(define or (lambda (x y)
             (cond ((eq? x y) (eq? x #t))
                   (#t #t)
                   )
             )
  )

(define and (lambda (x y)
              (cond ((eq? x y) (eq? x #t))
                    (#t #f)
                    )
              )
  )

(define atom? (lambda (x)
                (not (pair? x))
                )
  )

(define length (lambda (x)
                       (cond ((eq? x '()) 0)
                             ((atom? x) 1)
                             (#t (+ (length (car x)) (length (cdr x))))
                             )
                       )
  )

(define equal? (lambda (x y)
                 (cond ((and (atom? x) (atom? y)) (eq? x y))
                       ((not (eq? (length x) (length y))) #f)
                       ((not (and (pair? x) (pair? y))) #f)
                       (#t (and (equal? (car x) (car y)) (equal? (cdr x) (cdr y))))
                       )
                 )
  )

(define is-in? (lambda (x y)
                 (cond ((equal? x y) #t)
                       (#t (cond ((pair? y) (or (is-in? x (car y)) (cond ((eq? (length y) 1) #f)
                                                                          (#t (is-in? x (cdr y)))
                                                                          )))
                                 (#t #f)
                                 )
                           )
                       )
                 )
  )

更新

我想要的是拥有一般功能,它可以告诉您某个对象是否在另一个对象中。我将实体命名为 object ,以强调该函数应该适用于任何输入值,简单或复杂如地狱。

示例用法:

1. (is-in? 1 '(1 2 3)) ;-> #t
2. (is-in? '(1) '(1 2 3)) ;-> #f
3. (is-in? '(2 . 3) '(1 2 . 3)) ;-> #f
4. (is-in? '(2 . 3) '(1 (2 . 3))) ;-> #t
5. (is-in? '2 '(1 2 . 3)) ;-> #t
6. (is-in? '(2) '(1 2 . 3)) ;-> #f
7. (is-in? '(1 2 (3 4 (5 6 . (7 . 8)) 9) 10 11 (12 . 13)) '(1 (2 3 ((4 ((6 (3 . ((1 2 (3 4 (5 6 . (7 . 8)) 9) 10 11 (12 . 13)))) 3) 4)) 5) 2))) ;-> #t
8. (is-in? '(2 3 4) '((1 (2 3 4)) (1 2 3 4))) ;-> #t
9. (is-in? '(2 3 4) '(1 2 3 4)) ;-> #f
10. (is-in? '(2 3 4) '(1 (2 3 4))) ;-> #t
11. (is-in? '(1) '(1)) ;-> #t

2 个答案:

答案 0 :(得分:2)

(define (is-in? e lst)
   (cond ((null? lst) #f) ; if list is empty, we failed
         ((eq? e (car lst)) #t) ; check 1st element of list
         ((list? (car lst)) (is-in? e (append (car lst) (cdr lst)))) ; search inside car if it is a list
         (#t (is-in? e (cdr lst))))) ; check rest of list

您可以用更精细的内容替换eq?以处理其他相等的定义。

注意:这假设所有序列都是列表;你必须调整它来处理不是列表的点对。

答案 1 :(得分:2)

首先 - 您为什么要重新定义andorequal?length?那些都是内置的原语。您对atom?的定义也是错误的,应该是:

(define (atom? x)
  (and (not (pair? x))
       (not (null? x))))

我想你需要从头开始实现这个作为家庭作业的一部分。让我们看看如何实现这一目标,填写空白以获得答案:

(define (is-in? ele lst)
  (or <???>                          ; trivial case: ele == list
      (member? ele lst)))            ; call helper procedure

(define (member? ele lst)
  (cond ((null? lst)                 ; if the list is empty
         <???>)                      ; then the element is not in the list
        ((atom? lst)                 ; if the list is not well-formed
         (equal? <???> <???>))       ; then test if ele == list
        (else                        ; otherwise
         (or (equal?  ele <???>)     ; test if ele == the 1st element in the list
             (member? ele <???>)     ; advance the recursion over the `car`
             (member? ele <???>))))) ; advance the recursion over the `cdr`

请注意,需要member?中的第二种情况,因为在给出的示例中存在格式错误的列表(以非空值结尾)。上述解决方案将正确处理问题中提供的所有示例。