Jump to content

Replace item at sublist


rog1n
 Share

Recommended Posts

Hello, I am trying create a function that replace a item from a list with sublist (like a tree) with a sublist, so at momento I do this:

 

 

(defun test (lst o n)
  (if lst
    (cond
      ((= (type (car lst)) 'LIST)
        (list (test (car lst) o n))
      )
      ((atom (car lst))
       (if (equal o (car lst))
	 (cond
	   ((atom n) (cons n (test (cdr lst) o n)))
	   ((= (type n) 'LIST) (cons n (test (cdr lst) o n)))
	 )
	 (cons (car lst) (test (cdr lst) o n))
       )
      )
    )
   )
)

 

if I execute with this list: 
(setq number (list 1 (list 2 (list 3 (list 4 5)))))
(test number 5 (list 5 6))
--> result is (1 (2 (3 (4 (5 6))))) work like I need

but if I tried with this list:
(setq number2 (list 1 (list 2 (list 3 (list 4 5))) 7))

(test number2 5 (list 5 6))
--> result is (1 (2 (3 (4 (5 6))))) dont work, the correct result is: (1 (2 (3 (4 (5 6)))) 7)

 

or

(test number2 7 (list 7 8))

--> result is (1 (2 (3 (4 5)))) dont work, the correct result is: (1 (2 (3 (4 5))) (6 7))

 

If possible, anyone can help me to fix the code?

Link to comment
Share on other sites

https://documentation.help/AutoLISP-Functions/WS1a9193826455f5ff1a32d8d10ebc6b7ccc-689a.htm

 

;;---------------------=={ Subst Nth }==----------------------;;
;;                                                            ;;
;;  Substitutes an item at the nth position in a list.        ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2011 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  a - item to substitute                                    ;;
;;  n - position in list to make the substitution             ;;
;;  l - list in which to make the substitution                ;;
;;------------------------------------------------------------;;
;;  Returns:  Resultant list following the substitution       ;;
;;------------------------------------------------------------;;

b - item to be replaced

(defun LM:SubstNth ( a b l / i n)
  (vl-load-com)
  (setq i -1)
  (if (setq n (vl-position b l))
    (mapcar '(lambda ( x ) (if (= (setq i (1+ i)) n) a x)) l)
  )
)


(LM:SubstNth 10 4 '(5 4 3 2 1 0))
(5 10 3 2 1 0)

 

Edited by mhupp
Link to comment
Share on other sites

Still nothing work I belive its because I have list inside others list

 

check the example:

 

(setq lst  (list 1 (list 2 (list 3 (list 4 5)))))
(LM:SubstNth 5 6 lst) -> nil

 

Link to comment
Share on other sites

1 hour ago, mhupp said:

Any reason your running 3 or 4 levels deep with lists?

 

I am trying make a scheme with parent and child

image.png.1e38945e164c972cec6fb9abeb4353fd.png

 

Do you have a better solution?

  • Like 1
Link to comment
Share on other sites

I don't know exactly how to explain it.. either I will look brilliant by saying what I think or everyone will say "no it's not that at all you fool". Anyway I think it is all to do with moving along the nested lists until there is no more lists but it can't then 'un-nest' back up the levels.. I think...

 

So what I thought is you might need to explicitly loop through each item in the list and analyse that as you loop through and repeat as you come to a new nested list, when that nested list is finished the loop moves onto the next item in its parent list.. or something like that

 

Anyway, you could try this:

(defun testlist (mylist mysearchterm myreplace / Newlist)
  (defun checklist ( alist mysearchterm myreplace / acount mylist)
    (defun LM:SubstNth ( a n l )
      (if l
        (if (zerop n)
          (cons a (cdr l))
          (cons (car l) (LM:SubstNth a (1- n) (cdr l)))
        )
      )
    )

    (setq acount 0)
    (while (< acount (length alist))
    (if (= (TYPE (nth acount alist)) 'LIST)
      (setq mylist (LM:SubstNth (checklist (nth acount alist) mysearchterm myreplace ) acount alist))

      (progn ;;if not list
        (if ( = (nth acount alist) mysearchterm)
          (setq mylist (LM:SubstNth myreplace acount alist))
        ) ; end if
      ) ; end progn
    ) ; end if
    (setq acount (+ acount 1))
    ) ; end while
    mylist
  )

  (princ "My Old List: ")
  (princ mylist)
  (princ ". Subs: ")
  (princ mysearchterm)
  (princ ". New Item: ")
  (princ myreplace)

  (setq Newlist (checklist mylist mysearchterm myreplace))

  (princ " : My New List: ")
  (princ Newlist)
  (princ)
)

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

47 minutes ago, Steven P said:

I don't know exactly how to explain it.. either I will look brilliant by saying what I think or everyone will say "no it's not that at all you fool". Anyway I think it is all to do with moving along the nested lists until there is no more lists but it can't then 'un-nest' back up the levels.. I think...

 

So what I thought is you might need to explicitly loop through each item in the list and analyse that as you loop through and repeat as you come to a new nested list, when that nested list is finished the loop moves onto the next item in its parent list.. or something like that

 

Anyway, you could try this:

(defun testlist (mylist mysearchterm myreplace / Newlist)
  (defun checklist ( alist mysearchterm myreplace / acount mylist)
    (defun LM:SubstNth ( a n l )
      (if l
        (if (zerop n)
          (cons a (cdr l))
          (cons (car l) (LM:SubstNth a (1- n) (cdr l)))
        )
      )
    )

    (setq acount 0)
    (while (< acount (length alist))
    (if (= (TYPE (nth acount alist)) 'LIST)
      (setq mylist (LM:SubstNth (checklist (nth acount alist) mysearchterm myreplace ) acount alist))

      (progn ;;if not list
        (if ( = (nth acount alist) mysearchterm)
          (setq mylist (LM:SubstNth myreplace acount alist))
        ) ; end if
      ) ; end progn
    ) ; end if
    (setq acount (+ acount 1))
    ) ; end while
    mylist
  )

  (princ "My Old List: ")
  (princ mylist)
  (princ ". Subs: ")
  (princ mysearchterm)
  (princ ". New Item: ")
  (princ myreplace)

  (setq Newlist (checklist mylist mysearchterm myreplace))

  (princ " : My New List: ")
  (princ Newlist)
  (princ)
)

 

 

 

 

I am trying to understand what you do, anyway its working like I need,

thank you all for the help!

  • Like 1
Link to comment
Share on other sites

Hi

Here is a simple function, works for any nesting level

(defun replace_sublist (lst old new)
  (mapcar
    (function
      (lambda (x)
        (cond
          ((equal x old) new)
          ((atom x) x)
          (T (replace_sublist x old new))
        )
      )
    )
    lst
  )
)

And some tests

_$ (setq number2 (list 1 (list 2 (list 3 (list 4 5))) 7))
(1 (2 (3 (4 5))) 7)

_$ (replace_sublist number2 5 (list 5 6))
(1 (2 (3 (4 (5 6)))) 7)

_$ (replace_sublist number2 7 (list 7 8))
(1 (2 (3 (4 5))) (7 8))

_$ (replace_sublist number2 (list 4 5) 4)
(1 (2 (3 4)) 7)
_$ 

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...