[LISP] LIST

[LISP] LIST

iBlachu
Advocate Advocate
687 Views
6 Replies
Message 1 of 7

[LISP] LIST

iBlachu
Advocate
Advocate

How to convert any sublist to one list?

 

Exapmle:

(1 2 (3 4 (5) 6) 7 8 (9))

to

(1 2 3 4 5 6 7 8 9)

0 Likes
Accepted solutions (2)
688 Views
6 Replies
Replies (6)
Message 2 of 7

ВeekeeCZ
Consultant
Consultant
Accepted solution
(defun :plainlist (lin / :sub lout)
  (defun :sub (lin)
    (foreach e lin
      (if (listp e)
	(:sub e)
	(setq lout (cons e lout))))
    (reverse lout))
  (:sub lin))

 

>> (:plainlist '(1 2 (3 4 (5) 6) 7 8 (9)))

>> (1 2 3 4 5 6 7 8 9)

 

Message 3 of 7

dbroad
Mentor
Mentor
Accepted solution
(defun flatten (lst)
  (cond
    ((null lst) nil)
    ((atom (car lst))
     (cons (car lst)
	   (flatten (cdr lst))))
     (t (append
	  (flatten (car lst))
	  (flatten (cdr lst))))))
Architect, Registered NC, VA, SC, & GA.
Message 4 of 7

martti.halminen
Collaborator
Collaborator

Another variant:

(defun flatten2 (lst)
  (if (null lst)
      nil
      (flat2 lst)))

(defun flat2 (lst)
  (cond ((null lst) (list nil))
        ((atom lst) (list lst))
        (T (apply (function append)
                  (mapcar (function flat2)
                          lst)))))
Message 5 of 7

Kent1Cooper
Consultant
Consultant

Here's a cockamamie way to do it -- just take all the parentheses out:

 

(defun flatlist (oldlist / test str)
  (setq test (open "C:/temp/junk.txt" "w")); <--EDIT filepath/name to suit
  (prin1 oldlist test); puts into file AS TEXT STRING
  (close test)
  (setq
    test (open "C:/temp/junk.txt" "r")
    str (read-line test); bring text-string version in
  )
  (close test)
  (while (wcmatch str "*(*") (setq str (vl-string-subst "" "(" str))); remove left parentheses
  (while (wcmatch str "*)*") (setq str (vl-string-subst "" ")" str))); remove right parentheses
  (setq newlist (read (strcat "(" str ")"))); put outer parentheses list wrapper back
)

 

(setq yourlist '(1 2 (3 4 (5) 6) 7 8 (9)))

Command: (flatlist yourlist)
(1 2 3 4 5 6 7 8 9)

 

And yes, in this case it's a real list of integers:

Command: (apply '+ newlist)
45

 

(setq otherlist '(1 (2 (3 (4 (5 6 7) (8 9))))))

Command: (flatlist otherlist)

(1 2 3 4 5 6 7 8 9)

 

(setq mylist '(1 "who" (3 4 ("what") 6) 7 "when" (9)))

Command: (flatlist mylist)

(1 "who" 3 4 "what" 6 7 "when" 9)

 

(setq anotherlist '(1.234 9.876 (5 4 3) "Marilyn Monroe" pi ("Yes" "No")))

Command: (flatlist anotherlist)
(1.234 9.876 5 4 3 "Marilyn Monroe" PI "Yes" "No")

 

And yes, PI there is the real symbol:
Command: (eval (nth 6 newlist))
3.14159

Kent Cooper, AIA
Message 6 of 7

martti.halminen
Collaborator
Collaborator

You could replace 

(while (wcmatch str "*(*") (setq str (vl-string-subst "" "(" str))); remove left parentheses
(while (wcmatch str "*)*") (setq str (vl-string-subst "" ")" str))); remove right parentheses

with

(setq str (vl-string-translate "()" "  " str))

 

Either way, this is a little risky: if the data contains strings with have parentheses inside, this will remove also those:

 

_$ (flatlist '(("A" "B+(C-D)")))
("A" "B+C-D")

 

_$ (flatten2 '(("A" "B+(C-D)"))) ;; or any of the list structure -based flatteners
("A" "B+(C-D)")

 

0 Likes
Message 7 of 7

Kent1Cooper
Consultant
Consultant

@martti.halminen wrote:

.... this is a little risky: if the data contains strings with have parentheses inside, this will remove also those: ....


Yes, that had occurred to me just after posting, and justifies my use of the adjective:

  Kent1Cooper_1-1643029608574.png

Kent1Cooper_2-1643029639554.png

Besides, it takes more code to do it that way than some of the other approaches [maybe not so much under your (vl-string-translate) suggestion, though that adds extraneous spaces].

Kent Cooper, AIA
0 Likes