在列表中的列表中查找列表元素

时间:2013-10-08 14:03:54

标签: scheme

我需要一个过程,它接受一个列表并检查一个元素是否是该列表的一部分,即使该列表包含列表。到目前为止,我写过:

(define (element-of-set? element set)
    (cond ((null? set) #f)
    ((eq? element (car set)) #t)
    (else (element-of-set? element (cdr set))))))

但是,如果你有一个如下所示的列表:

(a (a b b (c b) 3) 5 5 (e s) (s e s))

然后我的书面element-of-set?无法识别3是此列表的一部分。我做错了什么?

3 个答案:

答案 0 :(得分:0)

您不会在car论证的set内重复出现。

如果您评估

(element-of-set? 3 '(a (a b b (c b) 3) 5 5 (e s) (s e s)))

根据您当前的element-of-set?定义,它会执行类似

的操作
  • 检查是否(eq? 3 'a),nope。
  • 检查是否(eq? 3 '(a b b (c b) 3)),nope。
  • 检查(eq? 3 5),不是
  • 检查(eq? 3 5),不是
  • 检查(eq? 3 '(e s)),不是
  • 检查是否(eq? 3 '(s e s)),nope。
  • 我不在名单之列; 3不是'(a (a b b (c b) 3) 5 5 (e s) (s e s))
  • 的成员

如果要检查深层集合成员资格,则需要重新定义您的过程,以便在car set list时,如果该元素本身为... ((list? (car set)) (or (element-of-set? element (car set)) (element-of-set? element (cdr set)))) ... 。像

这样的东西
list?

应该这样做,假设实际定义了(not (atom? (car set)))(我在这台机器上没有方案解释器,所以我不确定。你可能需要使用{{1}}代替。) / p>

答案 1 :(得分:0)

不是根据列表列表进行思考,而是根据从对(也称为cons单元)构建的树进行思考,这可能是一个有用的地方。当您致电(cons x y)时,您会收到一个缺点,而x被称为cary被称为cdr。当您在某个对象e中搜索元素object时,您可以这样做:

  1. eobject相同吗?如果是这样,你就找到了它!
  2. (a)object是一对吗?如果是,请检查e中的car是否为(b),cdr中是否为(c),如果是,则表示您已找到它!
  3. 否则,你还没找到它,而且无处可寻。
  4. 转换为代码相对简单,您甚至可以使用orand使其变得非常干净:

    (define (tree-find e object)
      (or (eq? e object)                           ; 1.
          (and (pair? object)                      ; 2.a
               (or (tree-find e (car object))      ; 2.b
                   (tree-find e (cdr object))))))  ; 2.c
    

    现在,这甚至允许您在树中查找树的子部分。例如,如果您使用树'((1 2) (3 (4 5)) (6 7))并提取其第二个元素(列表(3 (4 5))),并询问其是否为成员,您将得到肯定的答案。请注意,这是因为您使用eq?进行检查,因此它只会找到相同的对象,而不只是具有相同结构的对象:

    (let* ((l '((1 2) (3 (4 5)) (6 7)))
           (e1 (cadr l))           ; (3 (4 5)), from l
           (e2 (list 3 '(4 5))))   ; (3 (4 5)), but not from l
      (display (tree-find e1 l))   ; #t
      (display (tree-find e2 l)))  ; #f
    

    但是,因为正确的列表由空列表终止(例如,(1 2 3)(1 . (2 . (3 . ())))),tree-find将始终说'()是成员,如果有的话输入中的正确列表。因此,您可能希望明确禁止这种情况:

    (define (tree-find e object)
      (or (and (eq? e object)
               (not (null? e)))                   ; check only non-null objects
          (and (pair? object)
               (or (tree-find e (car object))
                   (tree-find e (cdr object))))))
    

答案 2 :(得分:0)

您只需要另一个子句来检查car是否为列表。将其添加到您的cond(在eq?子句之后):

((list? (car set))
 (or (element-of-set? element (car set))
     (element-of-set? element (cdr set))))

这会对任何子列表进行处理。