rog1n Posted January 10, 2022 Posted January 10, 2022 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? Quote
rog1n Posted January 11, 2022 Author Posted January 11, 2022 6 minutes ago, mhupp said: http://lee-mac.com/substn.html Thank you for the reply, but unfortunately it doesn't help me, because I dont know the index of the item I want replace. Quote
mhupp Posted January 11, 2022 Posted January 11, 2022 (edited) 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 January 11, 2022 by mhupp Quote
rog1n Posted January 11, 2022 Author Posted January 11, 2022 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 Quote
mhupp Posted January 11, 2022 Posted January 11, 2022 Any reason your running 3 or 4 levels deep with lists? Quote
rog1n Posted January 11, 2022 Author Posted January 11, 2022 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 Do you have a better solution? 1 Quote
Steven P Posted January 11, 2022 Posted January 11, 2022 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) ) 1 1 Quote
rog1n Posted January 12, 2022 Author Posted January 12, 2022 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! 1 Quote
Stefan BMR Posted January 12, 2022 Posted January 12, 2022 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) _$ 1 1 Quote
Recommended Posts
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.