简体   繁体   中英

Common Lisp: Removing elements with the same cdr

(Assignment help, go easy on me) (I have to do this without using destructive functions (setf))

With common lisp, as part of some code I need to be able to:

Take a list of lists, compare the cdr of 2 elements, If equal disregard the first element, If not equal then try and compare the first element with the next unchecked element in the list.

Some examples to clarify:

((1 1 1) (2 1 1) (3 1 1)) -> ((3 1 1))

((2 2 0) (4 1 1) (1 2 0) (3 0 1) (8 1 1)) -> ((1 2 0) (3 0 1) (8 1 1))

(defun simplify2 (vari)
    ;If last term: stop
    (if (equal (cdr vari) nil) vari

        ;If cdr of first and second term are equal...
        (if (equal (cdar vari) (cdr (cadr vari)))

            ;Ignore the first term and continue with the rest of the list
            (simplify2 (cdr vari))

            ;Otherwise (this is the line which isn't working)
            (cons (car vari) (simplify2 (cdr vari))))))

At the moment the code will only work properly when all 'like' terms are placed next to each other in the list.

Le Petit Prince's suggestion in the comments to use remove-duplicates is probably what you want here. remove-duplicates is non-destructive (cf. delete-duplicates which can be destructive), and it's specified to a return a new list in which all but the last instance of an element are omitted (emphasis added):

remove-duplicates

remove-duplicates returns a modified copy of sequence from which any element that matches another element occurring in sequence has been removed. … The elements of sequence are compared pairwise, and if any two match, then the one occurring earlier in sequence is discarded , unless from-end is true, in which case the one later in sequence is discarded.

You'll need to specify the a key argument to indicate that what should actually be compared is the cdr of the elements, and a test argument to indicate that they should be compared with equal . Thus:

(remove-duplicates '((1 1 1) (2 1 1) (3 1 1))
                   :test 'equal 
                   :key 'cdr)
;=> ((3 1 1))

(remove-duplicates '((2 2 0) (4 1 1) (1 2 0) (3 0 1) (8 1 1))
                   :test 'equal
                   :key 'cdr)
;=> ((1 2 0) (3 0 1) (8 1 1))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM