How to remove nested parentheses in LISP

前端 未结 12 1420
清酒与你
清酒与你 2020-11-29 10:20

How can I remove nested parentheses recursively in Common LISP Such as

  (unnest \'(a b c (d e) ((f) g))) => (a b c d e f g)
  (unnest \'(a b))                    


        
相关标签:
12条回答
  • 2020-11-29 10:46

    I know this question is really old but I noticed that nobody used the push/nreverse idiom, so I am uploading that here.

    the function reverse-atomize takes out each "atom" and puts it into the output of the next call. At the end it produces a flattened list that is backwards, which is resolved with the nreverse function in the atomize function.

    (defun reverse-atomize (tree output)
        "Auxillary function for atomize"
        (if (null tree)
          output
          (if (atom (car tree))
              (reverse-atomize (cdr tree) (push (car tree) output))
              (reverse-atomize (cdr tree) (nconc (reverse-atomize (car tree)
                                                                   nil)
                                                  output)))))
    
    (defun atomize (tree)
        "Flattens a list into only the atoms in it"
         (nreverse (reverse-atomize tree nil)))
    

    So calling atomize '((a b) (c) d) looks like this:

    (A B C D)
    

    And if you were to call reverse-atomize with reverse-atomize '((a b) (c) d) this would occur:

    (D C B A)
    

    People like using functions like push, nreverse, and nconc because they use less RAM than their respective cons, reverse, and append functions. That being said the double recursive nature of reverse-atomize does come with it's own RAMifications.

    0 讨论(0)
  • 2020-11-29 10:50
    (defun flatten (l)
      (cond ((null l) nil)
            ((atom l) (list l))
            (t (loop for a in l appending (flatten a)))))
    
    0 讨论(0)
  • 2020-11-29 10:54

    Just leaving this here as I visited this question with the need of only flattening one level and later figure out for myself that (apply 'concatenate 'list ((1 2) (3 4) (5 6 7))) is a cleaner solution in that case.

    0 讨论(0)
  • 2020-11-29 10:56

    I realize this is an old thread, but it is one of the first that comes up when I google lisp flatten. The solution I discovered is similar to those discussed above, but the formatting is slightly different. I will explain it as if you are new to lisp, as I was when I first googled this question, so it's likely that others will be too.

    (defun flatten (L)
    "Converts a list to single level."
        (if (null L)
            nil
            (if (atom (first L))
                (cons (first L) (flatten (rest L)))
                (append (flatten (first L)) (flatten (rest L))))))
    

    For those new to lisp, this is a brief summary.

    The following line declares a function called flatten with argument L.

    (defun flatten (L)
    

    The line below checks for an empty list.

        (if (null L)
    

    The next line returns nil because cons ATOM nil declares a list with one entry (ATOM). This is the base case of the recursion and lets the function know when to stop. The line after this checks to see if the first item in the list is an atom instead of another list.

            (if (atom (first L))
    

    Then, if it is, it uses recursion to create a flattened list of this atom combined with the rest of the flattened list that the function will generate. cons combines an atom with another list.

                (cons (first L) (flatten (rest L)))
    

    If it's not an atom, then we have to flatten on it, because it is another list that may have further lists inside of it.

                (append (flatten (first L)) (flatten (rest L))))))
    

    The append function will append the first list to the start of the second list. Also note that every time you use a function in lisp, you have to surround it with parenthesis. This confused me at first.

    0 讨论(0)
  • 2020-11-29 10:56
    (defun flatten (l)
      (cond ((null l) nil)
            ((atom (car l)) (cons (car l) (flatten (cdr l))))
            (t (append (flatten (car l)) (flatten (cdr l))))))
    
    0 讨论(0)
  • 2020-11-29 10:57

    You could define it like this for example:

    (defun unnest (x)
      (labels ((rec (x acc)
        (cond ((null x) acc)
          ((atom x) (cons x acc))
          (t (rec (car x) (rec (cdr x) acc))))))
        (rec x nil)))
    
    0 讨论(0)
提交回复
热议问题