Flatten Nests Function in Lisp - need help understanding

前端 未结 3 1720
名媛妹妹
名媛妹妹 2020-12-06 23:29

I\'ve been trying to find a way to condense nested lists into numbers that go back in the original list, but I having some trouble.

I\'ve been looking at the flatte

相关标签:
3条回答
  • 2020-12-06 23:51
    1. If the element you are looking at is nil - it is the end of the list, return nil.

    2. If the element you are looking at is not a list return a list containing that element (I'm not actually sure this is a right thing to do, because given an atom, which is not a list, it would return a list with the atom, rather then the atom itself).

    3. Otherwise (if it is a list), loop through all elements of it and append all the flattened sub-trees, (which you flattened by calling flatten), then return them.

    This is short, but not the most efficient algorithm since append needs to go all the way to the end of the list in order to cons one part on the tail of another part. Below is slightly more convoluted, but looks like more efficient version of it:

    (defun flatten (x &optional y)
      (cond
        ((null x)
         (cond
           ((null y) nil)
           ((listp (car y))
            (flatten (car y) (cdr y)))
           (t (cons (car y) (flatten (cdr y))))))
        ((listp (car x))
         (flatten (car x) (if y (list (cdr x) y) (cdr x))))
        (t (cons (car x) (flatten (cdr x) y)))))
    

    The algorithm behind this function does something as follows:

    1. If we have neither first element, nor the rest - we did everything, so just return nil (end of the list).

    2. If there's no first element - split the second into the first and the rest and repeat.

    3. If there is the first element, cons it into the list, if there is a second element - keep it, otherwise, select the next element and repeat.

    EDIT: I changed the #3, because the interpretation was really vague / could be wrong.

    0 讨论(0)
  • 2020-12-06 23:55
    (defun flatten (l)
    

    Above defines a function FLATTEN with one argument called L.

      (cond
    

    IF

        ((null l) nil)
    

    the value of the argument L is the empty list, return the empty list.

        ((atom l) (list l))
    

    or if the argument L is an atom (i.e. not a list), then return a list with the atom as its only item.

        (t 
    

    or else we have a non-empty list

           (loop for a in l
    

    then loop through all the items in the list which is the value of L

            appending (flatten a)
    

    and append the results of flattening each list item.

    ))))
    
    0 讨论(0)
  • 2020-12-06 23:56

    In my day instead of (loop for a in l appending (g a)) we wrote (mapcan #'g l). Which is equivalent to (apply #'append (mapcar #'g l)), more or less:

    (defun flatten (l) (if l (if (atom l) (list l) (mapcan #'flatten l))))
    

    So what does it mean in this case? Imagine you call (flatten (list 1 2 3 4 5)). Each atom in your list gets enclosed in a list - becomes a singleton list, like (1) (2) etc. Then they all are appended together, giving us back ... the original list:

    ( 1 2 3 4 5 )
    
    ( (1) (2) (3) (4) (5) )
    
    ( 1 2 3 4 5 )
    

    So flattening a list of atoms is an id operation (in Common LISP, that's #'identity). Now imagine flattening a list which has atoms in it, and also a list of atoms. Again, each element of the list gets transformed by flatten and then they are all appended together. A list of atoms stays as itself, as we just saw. Atoms get enclosed each in a list. So appending will give us back all the atoms that were on two levels in the nested list, now flattened:

    ( 11 12 (1 2 3 4) 13 )
    
    ( (11) (12) (1 2 3 4) (13) )
    
    ( 11 12 1 2 3 4 13 )
    

    And so on and so forth, for more levels of nesting as well.

    NILs as elements in lists pose a problem. NIL is an empty list, and empty list contains nothing, so should not contribute anything. But NIL is also an atom. So we make a special case for it, to not enclose it in a singleton list - leave it as it is, so when appended, it'll just disappear.

    0 讨论(0)
提交回复
热议问题