Find an element of list in lists in list

前端 未结 3 1165
野趣味
野趣味 2021-01-28 05:58

I need a procedure which takes a list and checks if an element is part of that list even when the list contains lists. So far, I\'ve written this:

(define (elem         


        
3条回答
  •  夕颜
    夕颜 (楼主)
    2021-01-28 06:11

    Rather than thinking in terms of lists of lists, this may be a useful place to think in terms of a tree built from pairs (also known as cons cells). A cons cell is what you get back when you call (cons x y), and x is called its car, and y is called its cdr. When you're searching for an element e in some object object, you can do it this way:

    1. Is e the same as object? If so, you've found it!
    2. (a) Is object a pair? If so, then check whether e is (b) in its car or (c) in its cdr, and if so, then you've found it!
    3. Otherwise, you haven't found it, and it's nowhere to be found.

    This is relatively straightforward to translate into code, and you can even make it pretty clean using or and and:

    (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
    

    Now, this even allows you to find subparts of a tree within a tree. For instance, if you took the tree '((1 2) (3 (4 5)) (6 7)) and extracted its second element (the list (3 (4 5))), and ask whether its a member, you'll get an affirmative answer. Note that this works because you're checking with eq?, so it would only find the same object, not just one with the same structure:

    (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
    

    However, because a proper list is terminated by an empty list (e.g., (1 2 3) is (1 . (2 . (3 . ())))), tree-find will always say that '() is a member if there's a proper list in the input. As such, you might want to explicitly disallow that case:

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

提交回复
热议问题