Replacing an item in a list

Discussion in 'AutoCAD' started by Marcel Janmaat, Dec 15, 2004.

  1. (setq'lst '("E_SKL0101" "Enkelpolige schakelaar" "3" "3" "3" "132"))

    Can anybody point me in the right direction on how to replace the 'lets say,
    4th item in this list with another value? Do I have to reconstruct?
    Or might there be something like (replace (nth 3 lst) "6")

    M
     
    Marcel Janmaat, Dec 15, 2004
    #1
  2. Marcel Janmaat

    Jeff Mishler Guest

    (subst) will replace every occurance of an item in a list, so his example
    list that has 3 "3"'s would have all if them changed to "6".....

    Here's one way:

    (defun replace-element-in-list (idx newelement oldlist / newlist)
    (if (< idx (1- (length oldlist)))
    (progn
    (setq count -1)
    (while (< (setq count (1+ count)) idx)
    (setq newlist (cons (car oldlist) newlist)
    oldlist (cdr oldlist))
    )
    (setq newlist (cons newelement newlist))
    (setq newlist (append (reverse newlist) (cdr oldlist)))
    )
    )
    (if newlist
    newlist
    oldlist
    )
    )
     
    Jeff Mishler, Dec 15, 2004
    #2
  3. Marcel Janmaat

    Doug Broad Guest

    A recursive form:

    (defun replacenth (n item lst) ;;D. C. Broad, Jr.
    (if lst
    (if (zerop n)
    (cons item (cdr lst))
    (cons (car lst)(replacenth (1- n) item (cdr lst))))))


     
    Doug Broad, Dec 15, 2004
    #3
  4. Marcel Janmaat

    Doug Broad Guest

    Hi Luis,

    I don't understand. -->>> Is that you son code? <<<----

    I just whipped it up tonight. Course it could've been done
    before. I dunno. ;-)

    Regards,
    Doug
     
    Doug Broad, Dec 16, 2004
    #4
  5. Marcel Janmaat

    Doug Broad Guest

    If you're asking if its my son's code, I'm a junior. My
    son is Douglas III.

    I don't usually add the Jr. ;-)
     
    Doug Broad, Dec 16, 2004
    #5
  6. Marcel Janmaat

    Jeff Mishler Guest

    Why do I have such a hard time following/writing recursive functions? I
    spent the better part of an hour trying to come up with something close to
    that and I just could not get my brain to think that way. And even after
    studying what you posted I thought "Aha! It will fail if you pass it an n
    greater than the total number of elements" but, alas, it does not, it just
    returns the list unchanged......one of these days the proverbial light bulb
    will switch on and I will think of these first.......

    thanks Doug for enlightening me again.

    --
    Jeff
    check out www.cadvault.com
     
    Jeff Mishler, Dec 16, 2004
    #6
  7. Let me know when that happens and share
    some of it with me <g>
     
    Jason Piercey, Dec 16, 2004
    #7
  8. Marcel Janmaat

    Doug Broad Guest

    Luis,
    No problem. Sorry for the confusion. I get lazy and
    leave off the Jr. most of the time.
    Regards,
    Doug
     
    Doug Broad, Dec 16, 2004
    #8
  9. Marcel Janmaat

    Doug Broad Guest

    Jeff,
    Thanks for the praise. It helps that I took a college course in those
    kinds of things many years ago at Va Tech, using PL1. I've probably
    still got the notes somewhere in my garage. ;-)

    BTW: Anybody out there gonna watch the Sugar Bowl? Yee haa.

    Regards,
    Doug
     
    Doug Broad, Dec 16, 2004
    #9
  10. Try this:

    ; Marc'Antonio Alessi - http://xoomer.virgilio.it/alessi
    ; Function: ALE_Subst_Nth
    ;
    ; Description:
    ; returns a copy of the list with a new item substituted in place
    ; of the item in the nth position (NthPos)
    ;
    ; Arguments:
    ; NthPos = Integer - nth like
    ; NewItm = An atom or list
    ; In_Lst = A list
    ; InRLst = Original list reversed
    ;
    ; Return Values:
    ; A list with a new item substituted in place of the item in the
    ; nth position
    ; If NewItm = nil the nth item is removed
    ;
    ; Examples:
    ; (setq alist '((0 . A) (1 . B) (2 . C) (3 . D)))
    ;
    ; (ALE_Subst_Nth 1 "NEW" alist (reverse alist))
    ; Returns: ((0 . A) "NEW" (2 . C) (3 . D))
    ;
    ; (ALE_Subst_Nth 1 '(9 . Z) alist (reverse alist))
    ; Returns: ((0 . A) (9 . Z) (2 . C) (3 . D))
    ;
    ; (ALE_Subst_Nth 1 nil alist (reverse alist))
    ; Returns: ((0 . A) (2 . C) (3 . D))
    ;
    (defun ALE_Subst_Nth (NthPos NewItm In_Lst InRLst / LstLng OldItm)
    (if (> (setq LstLng (- (length In_Lst) (1+ NthPos))) -1)
    (progn
    (setq OldItm (nth NthPos In_Lst))
    (while
    (/=
    NthPos
    (length (setq InRLst (cdr (member OldItm InRLst))))
    )
    )
    (while
    (/=
    LstLng
    (length (setq In_Lst (cdr (member OldItm In_Lst))))
    )
    )
    (append (reverse InRLst) (if NewItm (list NewItm) nil) In_Lst)
    )
    In_Lst
    )
    )

    --

    Marc'Antonio Alessi
    http://xoomer.virgilio.it/alessi
    (strcat "NOT a " (substr (ver) 8 4) " guru.")

    --
     
    Marc'Antonio Alessi, Dec 16, 2004
    #10
  11. Marcel Janmaat

    Jürg Menzi Guest

    Hi devitg
    It's Dutch -> single terminal switch...¦-)

    Cheers
     
    Jürg Menzi, Dec 16, 2004
    #11
  12. Marcel Janmaat

    Jürg Menzi Guest

    Hi Marcel

    This is from my standard library:
    Code:
    ;
    ; == Function MeEditList
    ; Replace or delete a list item by position.
    ; Arguments [Type]:
    ;   Pos = Position in list [INT]
    ;   Val = New value [INT/REAL/STR/LIST/SYMBOL]
    ;   Lst = List [LIST]
    ; Return [Type]:
    ;   > Modified list [LIST]
    ; Notes:
    ;   - :vlax-null as Val argument deletes the specified item
    ;   - :vlax-null items are not allowed in the list argument
    ;
    (defun MeEditList (Pos Val Lst / Countr TmpLst)
    (setq Countr -1
    TmpLst (mapcar
    '(lambda (l)
    (if (= Pos (setq Countr (1+ Countr))) Val l)
    ) Lst
    )
    )
    (vl-remove :vlax-null TmpLst)
    )
    
    Cheers
     
    Jürg Menzi, Dec 16, 2004
    #12
  13. Thanx!

     
    Marcel Janmaat, Dec 16, 2004
    #13
  14. Marcel Janmaat

    Doug Broad Guest

    Juerg,
    I like the remove option.

    Regards,
    Doug
     
    Doug Broad, Dec 16, 2004
    #14
  15. Marcel Janmaat

    devitg Guest

    Hi Jurg , it should be a literal translation.
    As I see, it could be "single pole swicht"
    As a switch culd not have only one terminal , I need two at least.
     
    devitg, Dec 16, 2004
    #15
  16. For maniacs:

    (setq alist1 '("1" "2" "3" "4" "4" "5" "5" "5" "6" "7" "8" "9" "9" "9" "9"))
    (setq alist (atoms-family 1)) ; length = 734
    (setq alist2 (append alist alist alist alist))

    -----------------------------------------------------------------
    (timerU '(replacenth 350 "kkk" alist) 1000)
    (timerU '(ALE_Subst_Nth 350 "kkk" alist (reverse alist)) 1000)

    REPLACENTH > 1000 iterations: 0.55 secs.
    ALE_SUBST_NTH > 1000 iterations: 0.46 secs.
    -----------------------------------------------------------------
    (timerU '(replacenth 700 "kkk" alist2) 1000)
    (timerU '(ALE_Subst_Nth 700 "kkk" alist2 (reverse alist2)) 1000)

    REPLACENTH > 1000 iterations: 1.07 secs.
    ALE_SUBST_NTH > 1000 iterations: 1.75 secs.
    ----------------------------------------------------------------
    (timerU '(replacenth 1400 "kkk" alist2) 1000)
    (timerU '(ALE_Subst_Nth 1400 "kkk" alist2 (reverse alist2)) 1000)

    REPLACENTH > 1000 iterations: 2.11 secs.
    ALE_SUBST_NTH > 1000 iterations: 1.91 secs.
    ----------------------------------------------------------------
    (timerU '(SetNth 350 "kkk" alist) 1000)
    (timerU '(MeEditList 350 "kkk" alist) 1000)
    (timerU '(ALE_Subst_Nth 350 "kkk" alist (reverse alist)) 1000)

    SETNTH > 1000 iterations: 0.69 secs.
    MEEDITLIST > 1000 iterations: 0.97 secs.
    ALE_SUBST_NTH > 1000 iterations: 0.53 secs.
    ----------------------------------------------------------------
    (timerU '(SetNth 700 "kkk" alist2) 1000)
    (timerU '(MeEditList 700 "kkk" alist2) 1000)
    (timerU '(ALE_Subst_Nth 700 "kkk" alist2 (reverse alist2)) 1000)

    SETNTH > 1000 iterations: 2.82 secs.
    MEEDITLIST > 1000 iterations: 4.05 secs.
    ALE_SUBST_NTH > 1000 iterations: 2.08 secs.
    ----------------------------------------------------------------
    (timerU '(SetNth 1400 "kkk" alist2) 1000)
    (timerU '(MeEditList 1400 "kkk" alist2) 1000)
    (timerU '(ALE_Subst_Nth 1400 "kkk" alist2 (reverse alist2)) 1000)

    SETNTH > 1000 iterations: 2.82 secs.
    MEEDITLIST > 1000 iterations: 4.07 secs.
    ALE_SUBST_NTH > 1000 iterations: 2.46 secs.
    ----------------------------------------------------------------
    (timerU '(MeEditList 350 :vlax-null alist) 1000)
    (timerU '(ALE_Subst_Nth 350 nil alist (reverse alist)) 1000)

    MEEDITLIST > 1000 iterations: 1 secs.
    ALE_SUBST_NTH > 1000 iterations: 0.53 secs.
    ----------------------------------------------------------------
    (timerU '(MeEditList 5 :vlax-null alist1) 100000)
    (timerU '(ALE_Subst_Nth 5 nil alist1 (reverse alist1)) 100000)

    MEEDITLIST > 100000 iterations: 5.38 secs.
    ALE_SUBST_NTH > 100000 iterations: 5.23 secs.


    --

    Marc'Antonio Alessi
    http://xoomer.virgilio.it/alessi
    (strcat "NOT a " (substr (ver) 8 4) " guru.")

    --
     
    Marc'Antonio Alessi, Dec 17, 2004
    #16
  17. Yes it's Dutch.
    And yes, its a "single pole swicht".
    But what does it matter.
    The question was only about how t determin the nth item in a list.

    Who cares what the list looks like. ; )

    Marcel Janmaat
    from The Netherlands
     
    Marcel Janmaat, Dec 17, 2004
    #17
  18. Marcel Janmaat

    Doug Broad Guest

    From one maniac to another, grazie.

    BTW: 1) What are your conclusions? 2) Where is SetNth? 3)Did you time Jeff's?

    Thanks again.
     
    Doug Broad, Dec 17, 2004
    #18
  19. Hi Doug,
    (setq
    alist1 '("1" "2" "3" "4" "5" "11" "6" "7" "8" "9" "10" "11" "12")
    alist (atoms-family 1) ; length = 734
    alist2 (append alist alist alist alist)
    alist1R (reverse alist1)
    alistR (reverse alist)
    alist2R (reverse alist2)
    )
    ; Note: I use the reversed list to perform many subst in the
    ; same original list, reversing only one time

    ----------------------------------------------------------------
    (timerU '(replace-element-in-list 10 "kkk" alist1) 10000)
    (timerU '(SetNth 10 "kkk" alist1) 10000)
    (timerU '(replacenth 10 "kkk" alist1) 10000)
    (timerU '(ALE_Subst_Nth 10 "kkk" alist1 alist1R) 10000)

    REPLACE-ELEMENT-IN-LIST > 10000 iterations: 0.57 secs.
    SETNTH > 10000 iterations: 0.49 secs.
    REPLACENTH > 10000 iterations: 0.49 secs.
    ALE_SUBST_NTH > 10000 iterations: 0.49 secs.
    ----------------------------------------------------------------
    (timerU '(replace-element-in-list 2 "kkk" alist1) 10000)
    (timerU '(SetNth 2 "kkk" alist1) 10000)
    (timerU '(replacenth 2 "kkk" alist1) 10000)
    (timerU '(ALE_Subst_Nth 2 "kkk" alist1 alist1R) 10000)

    REPLACE-ELEMENT-IN-LIST > 10000 iterations: 0.40 secs.
    SETNTH > 10000 iterations: 0.48 secs.
    REPLACENTH > 10000 iterations: 0.37 secs.
    ALE_SUBST_NTH > 10000 iterations: 0.45 secs.
    ----------------------------------------------------------------
    (timerU '(replace-element-in-list 700 "kkk" alist) 1000)
    (timerU '(SetNth 700 "kkk" alist) 1000)
    (timerU '(replacenth 700 "kkk" alist) 1000)
    (timerU '(ALE_Subst_Nth 700 "kkk" alist alistR) 1000)

    REPLACE-ELEMENT-IN-LIST > 1000 iterations: 1.50 secs.
    SETNTH > 1000 iterations: 0.78 secs.
    REPLACENTH > 1000 iterations: 1.17 secs.
    ALE_SUBST_NTH > 1000 iterations: 0.63 secs.
    ----------------------------------------------------------------
    (timerU '(replace-element-in-list 2900 "kkk" alist2) 1000)
    (timerU '(SetNth 2900 "kkk" alist2) 1000)
    (timerU '(replacenth 2900 "kkk" alist2) 1000)
    (timerU '(ALE_Subst_Nth 2900 "kkk" alist2 alist2R) 1000)

    REPLACE-ELEMENT-IN-LIST > 1000 iterations: 5.36 secs.
    SETNTH > 1000 iterations: 2.93 secs.
    REPLACENTH > 1000 iterations: 4.71 secs.
    ALE_SUBST_NTH > 1000 iterations: 2.13 secs.
    ----------------------------------------------------------------

    Note that only with MeEditList and ALE_Subst_Nth
    you can remove an element in a list with the same function.

    (replace-element-in-list 10 nil alist1)
    ("1" "2" "3" "4" "5" "11" "6" "7" "8" "9" nil "11" "12")

    (SetNth 10 nil alist1)
    ("1" "2" "3" "4" "5" "11" "6" "7" "8" "9" nil "11" "12")

    (replacenth 10 nil alist1)
    ("1" "2" "3" "4" "5" "11" "6" "7" "8" "9" nil "11" "12")

    (ALE_Subst_Nth 10 nil alist1 alist1R)
    ("1" "2" "3" "4" "5" "11" "6" "7" "8" "9" "11" "12")

    (MeEditList 10 :vlax-null alist1)
    ("1" "2" "3" "4" "5" "11" "6" "7" "8" "9" "11" "12")


    ---
    depend of the kind of the list: length of the list,
    number of double elements and the position of the index.

    ....

    What are your conclusions?

    --

    Marc'Antonio Alessi
    http://xoomer.virgilio.it/alessi
    (strcat "NOT a " (substr (ver) 8 4) " guru.")

    --
     
    Marc'Antonio Alessi, Dec 17, 2004
    #19
  20. Marcel Janmaat

    John Uhden Guest

    Sorry I haven't had time to play, but I think I disagree with the findings.
    Doug's ingenious function is the clear winner.
    Using...
    (defun timer (fun n show / start stop)
    ;; Uhden's timer with optional "show" of evaluation
    (setq start (getvar "date"))
    (repeat n (eval fun))
    (setq stop (getvar "date"))
    (print (car fun))
    (princ ": ")
    (princ (strcat "Elapsed time for " (itoa n) " iterations: " (rtos (* 86400.0
    (- stop start)) 2 2) " secs."))
    (if show (prin1 (eval fun)))
    (princ)
    )

    and a new entry just for grins...
    (defun replace_nth (item n lst / i indexed)
    ;; Using an indexed approach presented by
    ;; Tony Tanzillo Jul 1 1999
    ;; in autodesk.autocad.customization
    (setq
    i -1
    indexed
    (mapcar
    '(lambda (x)
    (cons (setq i (1+ i)) x)
    )
    lst
    )
    )
    (mapcar 'cdr (subst (cons n item)(assoc n indexed) indexed))
    )

    and the following test list...
    (progn
    ;; Perform the time trials
    ;; Set up the test list:
    (setq i 0 Lst nil)
    (repeat 256
    (setq Lst (cons (cons i (chr i)) Lst)
    i (1+ i)
    )
    )
    (setq Lst (reverse Lst)
    Pos 1
    Item (cons Pos "TEST")
    )
    (timer '(replacenth Pos Item Lst) 1000 nil)
    (timer '(ALE_Subst_Nth Pos Item Lst (reverse Lst)) 1000 nil)
    (timer '(MeEditList Pos Item Lst) 1000 nil)
    (timer '(replace_nth Pos Item Lst) 1000 nil)
    )

    The results I get are...
    For Pos = 1
    REPLACENTH : Elapsed time for 1000 iterations: 0.14 secs.
    ALE_SUBST_NTH : Elapsed time for 1000 iterations: 1.02 secs.
    MEEDITLIST : Elapsed time for 1000 iterations: 1.32 secs.
    REPLACE_NTH : Elapsed time for 1000 iterations: 2.33 secs.

    For Pos = 128
    REPLACENTH : Elapsed time for 1000 iterations: 0.60 secs.
    ALE_SUBST_NTH : Elapsed time for 1000 iterations: 1.26 secs.
    MEEDITLIST : Elapsed time for 1000 iterations: 1.31 secs.
    REPLACE_NTH : Elapsed time for 1000 iterations: 2.35 secs.

    For Pos = 255
    REPLACENTH : Elapsed time for 1000 iterations: 1.27 secs.
    ALE_SUBST_NTH : Elapsed time for 1000 iterations: 1.41 secs.
    MEEDITLIST : Elapsed time for 1000 iterations: 1.32 secs.
    REPLACE_NTH : Elapsed time for 1000 iterations: 2.35 secs.
     
    John Uhden, Dec 18, 2004
    #20
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.