Author Topic: Replace item in list with new item  (Read 7652 times)

0 Members and 1 Guest are viewing this topic.

daron

  • Guest
Replace item in list with new item
« on: February 11, 2008, 03:15:00 PM »
I'm sure this has been discussed before, but I can't seem to get a search smaller than 4 pages and even that didn't give me what I wanted. What I need is to take an existing list: (-1234.32 345.54 0.0) and replace any item with a new value. I'm currently trying to iterate through the list, increase or decrease the value of each item except if the value is 0.0 and return the previous list with its new values. Here's what I have so far, but I'm not very good with combining apply and append. I'll try flipping apply and append, but if someone has any better ideas, please let me know. Thanks.
Was going to ask how to do this, but decided to throw mapcar at it instead of foreach and this is what I got.
Code: [Select]
(defun pointAdjust (pointList updn)
     (mapcar '(lambda (x)
   (if (/= x 0.0)
(updn x offset)
(+ x 0.0)
   )
      )
     (vlax-safearray->list pointlist)
     )
)
offset being a predetermined value of point adjustment, pointList being the list of points and updn being - or +. It's then called like:
Code: [Select]
(setq lleft (setoff ll -))
(setq uright (setoff ur +))
but I'm sure this is not news to most.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Replace item in list with new item
« Reply #1 on: February 11, 2008, 03:24:16 PM »
Whenever I'm dealing with reals and equality tests I use 'equal' instead of '='.  So I would rewrite it like so,
Code: [Select]
(defun pointAdjust (pointList updn)
     (mapcar '(lambda (x)
   (if (equal x 0.0 0.000001)
x
(updn x offset)
   )
      )
     (vlax-safearray->list pointlist)
     )
)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

JohnK

  • Administrator
  • Seagull
  • Posts: 10637
Re: Replace item in list with new item
« Reply #2 on: February 11, 2008, 03:42:49 PM »
Daron, remember recursion?

Study this and try to remember what is and why it is happening. (HINT: stack)

Code: [Select]
(defun copy-tree (x)
  ;; exact copy of a list.
  ;; (nested lists are this procedures specialty.)
  (if (atom x)
   x
   (cons (copy-tree (car x))
         (copy-tree (cdr x)))) )

Once you get that down we can step into building a procedure that does what you want based upon this programing model.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

daron

  • Guest
Re: Replace item in list with new item
« Reply #3 on: February 11, 2008, 04:47:28 PM »
Yes, I remember them. Could never quite create one that worked. Mapcar is about as close as I have gotten. Considering it seems to take more code using foreach than it does using mapcar to do the same thing, I thought I was doing pretty good with that. However, I'm open to improvement. I tested your copy-tree. All it does is spit back everything I told it. I remember it grabs each item and stacks them up, then returns the conglomeration then removes them back off the stack in reverse order. Something like that.

Tim, thanks for the thought (read: info). That is why I posted it, improvement (read: your thoughts).

JohnK

  • Administrator
  • Seagull
  • Posts: 10637
Re: Replace item in list with new item
« Reply #4 on: February 11, 2008, 05:13:27 PM »
It returns exactly what you passed to it because thats what its supposed to do (read the comments).

Commenting this code can look something like this. 

Code: [Select]
(defun copy-tree (x)
  ;; exact copy of a list.
  ;; (nested lists are this procedures specialty.)
  ;; EX: (copy-tree '(1 2 (3 (4 5) 6 (nil)) 7 ((8))))
  ;;  > (1 2 (3 (4 5) 6 (nil)) 7 ((8)))
  (if (atom x)                   ; If item is only one item
    x                            ; return the item else,
    (cons (copy-tree (car x))    ; build a list, sending the next item
                                 ; back thru itself along with
          (copy-tree (cdr x))    ; the remainder of the items,
                                 ; via backtrace.
                                 ;
                                 ; NOTE:
                                 ; last fuction `cons' returns assembled
                                 ; list of items or exact copy of what
                                 ; was passed to this procedure.
          )) )

But using this model we can build our own item replacer procedure.

Code: [Select]
(defun replace-item-in-tree (a b x)
  ;; replace item in a list.
  ;; (nested lists are this procedures specialty.)
  ;; EX:
  ;;    (replace-item-in-tree
  ;;            3
  ;;            30
  ;;            '(1 2 (3 (4 5) 6 (nil)) 7 ((8)))
  ;;       )
  ;;
  ;; >  (1 2 (30 (4 5) 6 (nil)) 7 ((8)))
  (if (atom x)
   (if (not (eq a x)) x b)
   (cons (replace-item-in-tree a b (car x))
        (replace-item-in-tree a b (cdr x)))))

make sense?

BTW, you can T.Willey's suggestion in the recursive model we just built.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

daron

  • Guest
Re: Replace item in list with new item
« Reply #5 on: February 11, 2008, 06:34:32 PM »
How does this thing know when to stop processing information? It's time to go home. err... to class. It's been a long day. I'll see if looking at this with new eyes tomorrow will help me understand it better. What I'd really like to have it do is increase the 0 and 1 elements in a point list and leave the 2 element alone. I'm only worried about processing x, y, z values on this one and I've realized that my current function will process any of the three as long as they're not 0.0, which isn't horrible, just not good.

JohnK

  • Administrator
  • Seagull
  • Posts: 10637
Re: Replace item in list with new item
« Reply #6 on: February 11, 2008, 10:40:25 PM »
It stops when the list is done. When there are no more items to process...

But, I was speaking in more general terms. Mine is more for processing any kind of list (It will dive into a list, no matter how nested it is, and ``allow you to do something''). Im not saying you cant do what you want with it its just a bit of overkill for a point list processor.

Point lists are relatively easy because, for the most part, they are always constructed the same.  Im using NetBSD on my server right at the moment let me get back to you in the morn when i can run tests and stuff. However as food for thought, i think you need to be modifying your ``updn'' procedure not building a work around / wrapper for it.

Then you could be using your procedure more like this:
(mapcar 'updn (vlax-safearray->list pointlist)) ...
Which would make the statement a bit more manageable in the future (when your maintaining your application).

later,
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

daron

  • Guest
Re: Replace item in list with new item
« Reply #7 on: February 12, 2008, 11:06:05 AM »
Well, here's the latest rendition.
Code: [Select]
;;;----------------Point List Adjuster--------------------------;
;;; Function to adjust the first two points in a list ;
;;; leaving the z value unaltered. ;
;;; Requires: vla-object from vla-getboundingbox or the like ;
;;; Usage: (PointAdjust var t) or nil ;
;;; T will adjust the x and y points in a positive direction ;
;;; nil will adjust the x and y points in a negative direction ;
;;;_____________________________________________________________;
;;;Author: Daron Rogers 2008 ;
;;;_____________________________________________________________;
     (defun PointAdjust (Array updn / PointList Remove Process)
  (setq PointList (vlax-safearray->list Array)
Remove   (last PointList)
Process   (reverse (member (nth 1 PointList)
   (reverse PointList)
   )
  )
  )
  (append
       (mapcar '(lambda (x)
     (if (not (equal x 0.0 0.00001))
  (if updn
       (+ x offset)
       (- x offset)
  )
  x
     )
)
       Process
       )
       (list Remove)
  )
     )
« Last Edit: February 12, 2008, 11:21:03 AM by Daron »

JohnK

  • Administrator
  • Seagull
  • Posts: 10637
Re: Replace item in list with new item
« Reply #8 on: February 12, 2008, 11:39:53 AM »
... Im so lost. Why are you using mapcar if all you want is the first two items in a list modified? Whats with the killing of the last item / reverse thingie in the setq statement?

Code: [Select]
(defun c:pointlisttest ( )
 (setq lst  (getpoint "\nPick or enter point: ")
       lst  (list
                 (1+ (car lst))
                 (1+ (cadr lst))
                 (caddr lst))
       );_ end setq
 )
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

daron

  • Guest
Re: Replace item in list with new item
« Reply #9 on: February 12, 2008, 12:19:29 PM »
I'm using mapcar, because originally I was just wanting to process the list with foreach. Then I realized that foreach went through too many hoops to take each item from a list and put its altered state back in place where it started. I realized that mapcar was ideal for this and started to use it. Then I realized that I didn't want to change the z value at all or at best make all z values 0.0, which I haven't added. While I was working on this, I knew there was an easier way, by just picking the list apart with car cadr and caddr, but what fun is that? I wanted to iterate through it. For some strange reason, I just don't like using cadddddddddr all that much. It's kinda like that idea of being beaten by the machine or beating the machine. It's a learning experience. As for the last item / reverse thingie? Here's my thought process. I was thinking it would be nice to have a pop function like in python. I started out to create one, but couldn't remove the popped item and realized that if I just reverse the list and tell member to start at point 1, then reverse it again, I had the list I wanted to in its order. The last item is like a static pop, of course I originally thought to use nth so I could have more flexibility, but decided to nix the idea, since I only want to work with three point lists. Adding a position value finder would be nice with what you were trying to show me with recursion. You could safely remove that item, alter the rest and replace the popped item back in its place. Does that make sense?

JohnK

  • Administrator
  • Seagull
  • Posts: 10637
Re: Replace item in list with new item
« Reply #10 on: February 12, 2008, 12:44:06 PM »
kinda but I think your making it WAY to complicated and inefficient. Operating via list pointers (car, cadr etc) is a lot more efficient then iterating a list.

Its like your doing that much more work; Its like if you wanted to go to the store but your shoes have to travel whole blocks for every block you start...If the store was 2/3rd the way down a block you'd have go all the way to the corner and then go back to the store. Thats wasteful walking (you can get arrested for that in some countries).

A list pop procedure? well thats a bit tricky casue you ``cant'' modify a variable out of scope (Im not saying that you `cant' perse, i have one i use, but that is neither here nor there. We can discuss that procedure if you really would like a list pop procedure.)


TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

daron

  • Guest
Re: Replace item in list with new item
« Reply #11 on: February 12, 2008, 12:50:28 PM »
 :-D I know. I remeber Stig once explaining using and not using variables and relating it to having variables was like having salt on the table, as opposed to not having variables was like having to go to the store each time you wanted to use the salt. I get what you're saying. I just like seeing what can be done. As for the pop function, I recall you doing some challenges with lists that are probably close to what you're talking about. I remember one that used apply append. It was really slick and I have it (somewhere).

Quote
(you can get arrested for that in some countries).
As far as I know, only in Israel on a Saturday. :-D

JohnK

  • Administrator
  • Seagull
  • Posts: 10637
Re: Replace item in list with new item
« Reply #12 on: February 12, 2008, 01:36:47 PM »
*lmao* ...I think i remember that one! If i remember right, he blew my doors clean off with that statement. He was/is an amazing lisper.

I dont think i posted any pop procedures cause for the most part they are just plain unnecessary for a lot of what we do (with lisp and coordinates).
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

daron

  • Guest
Re: Replace item in list with new item
« Reply #13 on: February 12, 2008, 01:53:16 PM »
Yes he did. He blew everyone's door off with that one.

So, how does one remove an item from a list by its position, altering the list and returning the removed item.

JohnK

  • Administrator
  • Seagull
  • Posts: 10637
Re: Replace item in list with new item
« Reply #14 on: February 12, 2008, 03:11:54 PM »
Yes he did. He blew everyone's door off with that one.

So, how does one remove an item from a list by its position, altering the list and returning the removed item.

I first made this one when i was studying a procedure from Vladimir Nesterovsky and trying to come up with alternate ideas and understanding of his.

Code: [Select]
(defun list-pop (lst / ~tval )
  ;; list-pop
  ;;
  ;; remove the first item from a list and redefne
  ;; the var containing that list.
  ;;
  ;; Example:
  ;; Given a list called "masterlist" with the
  ;; value of: (TWO ONE)
  ;;
  ;; !masterlist
  ;; (TWO ONE)
  ;;
  ;; (list-pop 'masterlist)
  ;; TWO
  ;;
  ;; (list-pop 'masterlist)
  ;; ONE
  ;;
  ;; !masterlist
  ;; nil
  ;;
  ;; By: John (Se7en) K
  ;;    (inspired by Vladimir Nesterovsky)
  ;;
  ;; 10.24.05
  (setq ~tval (eval lst))
  (set lst (cdr ~tval))
  (car ~tval) )
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org