Replacing an item in a list with another

Discussion in 'AutoCAD' started by Danv., Dec 13, 2004.

  1. Danv.

    Danv. Guest

    hello everyone

    Any1 knows how to replace an item(dotted pair) in a list with another item
    (dotted pair). I know about subst but that will replace all instances and
    that's not what I want to do. I have lots of dotted pair (1. "") in my list
    and I want to replace each one of these with an item from another list. How
    can I do this? Any help would be appreciated. Let me know if you need more
    info.

    Dan
     
    Danv., Dec 13, 2004
    #1
  2. Danv.

    Dann Guest

    see subst in lisp help.
     
    Dann, Dec 13, 2004
    #2
  3. Danv.

    Danv. Guest

    subst will replace all instances and I don't want that. For example, the first (1. "") to be replaced by (1. "A"). The second (1. "") to be replaced by (1. "Door"). The third (1. "") to be replaced by (1. "all internal doors") and so on.
    "Dann" <NoneSpecified> wrote in message see subst in lisp help.
     
    Danv., Dec 13, 2004
    #3
  4. Danv.

    T.Willey Guest

    How are you getting the information? Are they list of lists?

    I guess a little more information would be helpful.

    Tim
     
    T.Willey, Dec 13, 2004
    #4
  5. Danv.

    BillZ Guest

    Can you manipulate the lists?

    Command:(setq lst '((1 . "")(2 . "K")(1 . "")(5 . "ff")(1 . "")))
    ((1 . "") (2 . "K") (1 . "") (5 . "ff") (1 . ""))

    Command: (append (subst (cons 1 "X")(assoc 1 lst)(list (nth 0 lst)))(cdr lst))
    ((1 . "X") (2 . "K") (1 . "") (5 . "ff") (1 . ""))

    Bill
     
    BillZ, Dec 13, 2004
    #5
  6. Danv.

    Doug Broad Guest

    Dan,
    If you have a simple list, then something like the following might work
    for you.
    ;;D. C. Broad, Jr.
    ;;Replace an existing item using a list of replacments.
    ;;Example: (replace '("this" "is" "a" "test") '(1 . "") '((1 . "") (2 . "1") (1 . "")(3 .
    "2")(1 . "")(1 . "")))
    ;;Returns: ("this" (2 . "1") "is" (3 . "2") "a" "test")
    (defun replace (replacements exist lst)
    (if lst
    (if (equal (car lst) exist)
    (cons (car replacements)
    (replace (cdr replacements) exist (cdr lst)))
    (cons (car lst)
    (replace replacements exist (cdr lst))))))

    You could aslo create a similar function with arguments
    (replacesim replacementvalues key valuetoreplace lst)
    that would work more specifically with association lists without
    the need to format the replacment list like '((1 . "this")(1 . "is")(1 . "a") (1 .
    "test"))
     
    Doug Broad, Dec 13, 2004
    #6
  7. Danv.

    Danv. Guest

    Here's is a little background about the lisp routine. In AutoCAD 2005, we
    have tables and cells within the tables. I am creating a lisp routine that
    will look at the table and find the empty cells. It will then read from an
    external file and fill the empty cells in the table. When I get the entity
    (acad_table), it will list all the empty cell as (1. ""). Well I need to
    replace these with the items extracted from the external file. Hope that
    clears it up a bitl as to what i am trying to do.
     
    Danv., Dec 13, 2004
    #7
  8. Danv.

    T.Willey Guest

    Do the suggestions already posted help? If not, I'm not sure how help full I can be because I don't have 2005. But I will try if you need it.

    Tim
     
    T.Willey, Dec 13, 2004
    #8
  9. Danv.

    Danv. Guest

    Since you don't have AutoCAD 2005 then that's ok. Thanks for your help tho.
    I do appreciate you taking your time to look into it.

    full I can be because I don't have 2005. But I will try if you need it.
     
    Danv., Dec 13, 2004
    #9
  10. Danv.

    Danv. Guest

    Sorry if this sounds easy or stupid but now how do you replace the next (1.
    ""). If I know the nth element, can I just replace it with my desired value?
    If the answer is yes then how would I do it.
     
    Danv., Dec 13, 2004
    #10
  11. Danv.

    T.Willey Guest

    Sorry. But if you have something going, and need help with the code aspect of it, post it here and I'm pretty sure someone will be able to help you.

    Good luck with the code.
    Tim
     
    T.Willey, Dec 13, 2004
    #11
  12. Sorry if this sounds easy or stupid but now how do you replace the next
    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 14, 2004
    #12
  13. The previous is otherwise quite nice, but with very long lists might
    have problems with running out of stack space. In that case you'd need
    an iterative version, for example:

    (defun swap (key new-values data / result new-item)
    (foreach item data
    (setq result
    (if (equal item key)
    (progn
    (setq new-item (cons (car key) (car new-values)))
    (setq new-values (cdr new-values))
    (cons new-item result))
    (cons item result))))
    (reverse result))

    - this version has a slight problem if we run out of new values, and
    doesn't complain if there isn't anything to replace, either. Feel free
    to add features.
    --
     
    Martti Halminen, Dec 14, 2004
    #13
  14. P.S. Sorry about the indentation: this newsreader (Thunderbird) thinks
    it knows more about how I want the message look like than I do :-(

    A new try:
    --
     
    Martti Halminen, Dec 14, 2004
    #14
  15. Danv.

    Doug Broad Guest

    Hi Martii,
    Good translation to iterative form. While I seriously doubt that the
    version I posted will cause stack problems, well written iterative
    versions (like yours appears to be) generally outperform recursive
    forms by 10-15%.

    Regards,
    Doug
     
    Doug Broad, Dec 14, 2004
    #15
  16. ;; Try this:

    ;; Given test lists:
    (setq GivenNone (list "a" "b" "c"
    (cons 1 "a") (cons 1 "b") (cons 1 "c"))
    )
    (setq GivenSome (list (cons 1 "") "a" "b" "c"
    (cons 1 "a") (cons 1 "b") (cons 1 "c") (cons 1 ""))
    )

    (setq GivenEqual (list (cons 1 "") (cons 1 "b") (cons 1 "")
    "a" "b" "c" (cons 1 "a") (cons 1 "") (cons 1 "c")))

    (setq GivenMore (list (cons 1 "") (cons 1 "")
    "a" "b" "c" (cons 1 "a") (cons 1 "") (cons 1 "b")
    (cons 1 "c") (cons 1 ""))) ; return out of order.

    (setq GivenMore1 (list (cons 1 "") (cons 1 "") (cons 1 "")
    "a" "b" "c" (cons 1 "a") (cons 1 "b") (cons 1 "")
    (cons 1 "c"))) ; return out of order.

    ;; The dotted pair expression we wish to replace
    (setq ConsExpr (cons 1 "")) ; in the given assciation lists

    ;; with items from this list in order of replacement.
    (setq ReplaceList (list (cons 1 "TOM") (cons 1 "DICK") '(1 . "HARRY")))

    ;; This version only replaces as many elements from the ReplaceList
    ;; as there are ConsExpr elements in the GivenList. The order of the
    given list
    ;; is preserved as is the length.

    (defun ReplaceOnlyWith (ReplaceList GivenList ConsExpr / Elem Return Sub)
    (cond
    ( ConsExpr
    (while GivenList
    (setq Elem (car GivenList)
    GivenList (cdr GivenList)
    )
    (cond
    ( (equal Elem ConsExpr)
    (setq Sub (car ReplaceList))
    (cond
    ( Sub
    (setq Return (cons Sub Return)
    ReplaceList (cdr ReplaceList)
    )
    )
    ( T
    (setq Return (cons Elem Return))
    )
    ) ;end cond.
    )
    ( T
    (setq Return (cons Elem Return))
    )
    ) ;end cond.
    ) ;end while
    (setq Return (reverse Return))
    )
    ( T
    (setq Return GivenList)
    )
    ) ;end cond.
    Return
    ) ;end ReplaceWith 12/14/2004


    ;GivenNone -> ("a" "b" "c" (1 . "a") (1 . "b") (1 . "c"))
    ;(ReplaceOnlyWith ReplaceList GivenNone ConsExpr)
    ;-> ("a" "b" "c" (1 . "a") (1 . "b") (1 . "c"))

    ;GivenSome ->((1 . "") "a" "b" "c" (1 . "a")
    ; (1 . "b") (1 . "c") (1 . ""))
    ;(ReplaceOnlyWith ReplaceList GivenSome ConsExpr)
    ;-> ((1 . "TOM") "a" "b" "c" (1 . "a")
    ; (1 . "b") (1 . "c") (1 . "DICK"))


    ;GivenEqual -> ((1 . "") (1 . "") (1 . "") "a" "b" "c"
    ; (1 . "a") (1 . "b") (1 . "c"))
    ;(ReplaceOnlyWith ReplaceList GivenEqual ConsExpr)
    ;-> ((1 . "TOM") (1 . "DICK") (1 . "HARRY") "a" "b" "c"
    ; (1 . "a") (1 . "b") (1 . "c"))

    ;GivenMore -> ((1 . "") (1 . "") (1 . "") "a" "b" "c"
    ; (1 . "a") (1 . "b") (1 . "c") (1 . ""))
    ;(ReplaceOnlyWith ReplaceList GivenMore ConsExpr)
    ;-> ((1 . "TOM") (1 . "DICK") (1 . "HARRY") "a" "b" "c"
    ; (1 . "a") (1 . "b") (1 . "c") (1 . ""))

    ;GivenMore1 -> ((1 . "") (1 . "") (1 . "") "a" "b" "c"
    ; (1 . "a") (1 . "b") (1 . "") (1 . "c"))
    ;(ReplaceOnlyWith ReplaceList GivenMore1 ConsExpr)
    ;-> ((1 . "TOM") (1 . "DICK") (1 . "HARRY") "a" "b" "c"
    ; (1 . "a") (1 . "b") (1 . "") (1 . "c"))


    ;; What I don't understand is why you are using dotted pairs like (1
    ;; . "") and (1 ."TOM"), you could simplify to ("") and ("Tom"). It
    ;; would make sense if the keys (1 in this case) were unique for
    ;; each element like ("1-10" . "") and ("1-10" . "TOM"), then you
    ;; could replace using the simple subs function. If your data is
    ;; from a table, why can't you make your keys incremental indexes of
    ;; Row-Col as above. For example, if the data were in row 20 and col
    ;; 3 you could make the key "20-3". The program that creates the
    ;; list should know the row and column. It would be worth the effort
    ;; to straighten out this detail as a solution instead of having to
    ;; create a complex non-standard function as above.

    ;; Larry
     
    Larry Leuallen, Dec 14, 2004
    #16
  17. Danv.

    BillZ Guest

    Danv,
    Sorry i missed your reply.
    If the answer is yes then how would I do it?<<<

    It would depend on the structure of the 2 lists.

    Are they the same length?
    Are the assoc 1's in the same order and the same quantity in each list.

    A sample of each list would be most helpful.

    Bill
     
    BillZ, Dec 15, 2004
    #17
  18. Danv.

    CAB2k Guest

    Try this:

    ;; CAB 12/13/04
    ;; Replace old from list items with new list items
    ;; new - ((1. "New01") (1. "New02") (1. "New03") (1. "New04") (1. "New05"))
    ;; old - (1 . "")
    ;; lst - ((1 . "") (2 . "1") (1 . "") (3 . "2")(1 . "")(1 . ""))
    ;; Result - ((1.0 "New01") (2 . "1") (1.0 "New02") (3 . "2") (1.0 "New03") (1.0 "New04"))
    (defun replace (new old lst / newitem nlst itm)
    (setq newitem (car new)
    new (cdr new)
    nlst '()
    )
    (foreach itm lst
    (if (and newitem (equal itm old))
    (setq nlst (cons newitem nlst)
    newitem (car new)
    new (cdr new)
    )
    (setq nlst (cons itm nlst))
    )
    )
    (reverse nlst)
    )
     
    CAB2k, Dec 15, 2004
    #18
  19. Danv.

    BillZ Guest

    The code I posted is much more efficient.

    Try this:

    ;; CAB 12/13/04
     
    BillZ, Dec 15, 2004
    #19
  20. Danv.

    CAB2k Guest

    Bill here is a time test of the different codes, I could be in error.
    Your code is much more elegant than mine. I still have trouble working with Mapcar lambda


    Bill here is your code example:
    (defun replaceBZ (new old lst)
    (apply 'append (mapcar '(lambda (a b)(if (= (car a) old)(subst b a (list a))(list a))) lst new))
    )

    Run time for 1000 times
    (replace '((1 . "New01") (1 . "New02") (1 . "New03") (1 . "New04") (1 . "New05")) 1
    '((1 . "") (2 . "1") (1 . "") (3 . "2")(1 . "")(1 . "")))


    Elapsed time: 0.040000 seconds

    Command:
    Command: timer
    Elapsed time: 0.040000 seconds

    Command:
    Command: timer
    Elapsed time: 0.041000 seconds

    Command:
    Command: timer
    Elapsed time: 0.040000 seconds

    Command:
    Command: timer
    Elapsed time: 0.040000 seconds

    Command:
    Command: timer
    Elapsed time: 0.041000 seconds

    Here are my times ////////////////////////////

    Command:
    Command: timer
    Elapsed time: 0.020000 seconds

    Command:
    Command: timer
    Elapsed time: 0.030000 seconds

    Command:
    Command: timer
    Elapsed time: 0.030000 seconds

    Command:
    Command: timer
    Elapsed time: 0.030000 seconds

    Command:
    Command: timer
    Elapsed time: 0.020000 seconds

    Command:
    Command: timer
    Elapsed time: 0.030000 seconds

    Command:
    Command: timer
    Elapsed time: 0.020000 seconds

    Command:
    Command: timer
    Elapsed time: 0.021000 seconds

    Using this as the timer.

    ;;=============================================================

    (defun startTimer ()
    (setq time (getvar "MILLISECS"))
    )
    ;;=============================================================

    (defun endTimer (func)
    (setq time (/ (- (getvar "MILLISECS") time) 1000.0))
    (princ (strcat "Elapsed time: " (rtos time 2 6) " seconds"))
    (gc)
    )

    ;;=============================================================
    ;;=============================================================
    (defun instest (/ ms ins)
    (startTimer)
    (repeat 1000
    (replace '((1 . "New01") (1 . "New02") (1 . "New03") (1 . "New04") (1 . "New05")) 1
    '((1 . "") (2 . "1") (1 . "") (3 . "2")(1 . "")(1 . "")))
    )
    (endTimer "instest")
    (princ)
    )


    ;;=============================================================

    (defun c:timer ()
    (INSTEST)
    (princ)
    )
     
    CAB2k, Dec 15, 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.