TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: Binky on July 16, 2009, 02:57:40 PM

Title: Perform operation to a single item in list
Post by: Binky on July 16, 2009, 02:57:40 PM
Hello folks,

New State, City, Job, Home, and everything else.  Took nearly a year but things have settled down enough to get back to coding so here I am again asking for your guidence.

I am kind of surprised that I have not needed/wanted to do this yet, but here I am trying to find a way to add a value to an existing value inside a list.

original list
(1 2 3 4 5)

I want to add 7 to the  3rd element something like this(only a version that works)
(setq (nth 2 list) (+(nth 2 list) 7))

list afterwards
(1 2 10 4 5 )

I can imagine ways to do this but they all involve creating a new list with the adjusted value.  Hoping for a easier solution, just drawing a blank today.
Title: Re: Perform operation to a single item in list
Post by: Lee Mac on July 16, 2009, 03:03:42 PM
I think I am drawing a blank too...

this is the best I have so far...    :|

Code: [Select]
(defun add (lst i)
  (mapcar
    (function
      (lambda (x)
        (if (eq i (vl-position x lst))
          (+ 7 x) x))) lst))

(add '(1 2 3 4 5) 2)
(1 2 10 4 5)

Title: Re: Perform operation to a single item in list
Post by: T.Willey on July 16, 2009, 03:12:47 PM
You may want to change the order of the arguments, so they flow better.

Code: [Select]
(defun AddAt ( inList loc num / cnt )
   
    (setq cnt -1)
    (mapcar
        (function
            (lambda ( x )
                (setq cnt (1+ cnt))
                (if (equal cnt loc)
                    (+ num x)
                    x
                )
            )
        )
        inList
    )
)

Command: (AddAt '(1 2 3 4 5) 2 7)

(1 2 10 4 5)
Title: Re: Perform operation to a single item in list
Post by: T.Willey on July 16, 2009, 03:21:58 PM
Another, more versatile, function.

Code: [Select]
(defun PerformAt ( func loc inList / cnt )
   
    (setq cnt -1)
    (mapcar
        (function
            (lambda ( x )
                (setq cnt (1+ cnt))
                (if (equal cnt loc)
                    (func x)
                    x
                )
            )
        )
        inList
    )
)

Command: (performat (lambda (x) (+ 3 x)) 3 '(1 2 3 4 5 6 7))
(1 2 3 7 5 6 7)
Title: Re: Perform operation to a single item in list
Post by: VovKa on July 16, 2009, 03:40:53 PM
Code: [Select]
(defun test (lst n func)
  (if lst
    (if (zerop n)
      (cons (func (car lst)) (cdr lst))
      (cons (car lst) (test (cdr lst) (1- n) func))
    )
  )
)
;;;(test '(1 2 3 4 5) 2 (lambda (e) (+ e 7)))
Title: Re: Perform operation to a single item in list
Post by: CAB on July 16, 2009, 03:49:06 PM
Code: [Select]
;; variation by CAB
(defun adjust_nth (opr num lst i)
  (setq i (1+ i))
  (mapcar '(lambda (x) (if (zerop (setq i (1- i))) (opr num x) x)) lst)
)

Code: [Select]
_$ (adjust_nth + 3 '(1 2 3 4 5 6 7) 4)
(1 2 3 4 8 6 7)
Title: Re: Perform operation to a single item in list
Post by: Lee Mac on July 16, 2009, 03:57:55 PM
Nice Alan, I've seen you use that method before, in your remove_nth function  :-)
Title: Re: Perform operation to a single item in list
Post by: Lee Mac on July 16, 2009, 03:59:13 PM
You may want to change the order of the arguments, so they flow better.

I don't understand what you mean Tim  :?
Title: Re: Perform operation to a single item in list
Post by: Binky on July 16, 2009, 04:09:06 PM
Humbled and grateful

Thanks tons!!!!

Title: Re: Perform operation to a single item in list
Post by: T.Willey on July 16, 2009, 04:10:41 PM
You may want to change the order of the arguments, so they flow better.

I don't understand what you mean Tim  :?

The way it is written is ' add at list location number '.  It might be better written ' add at location number list '.  Slight modification, but will sound better when you say it, or think about it.  At least I think so.
Title: Re: Perform operation to a single item in list
Post by: Lee Mac on July 16, 2009, 04:39:39 PM
You may want to change the order of the arguments, so they flow better.

I don't understand what you mean Tim  :?

The way it is written is ' add at list location number '.  It might be better written ' add at location number list '.  Slight modification, but will sound better when you say it, or think about it.  At least I think so.

Ahh, I see  :-)
Title: Re: Perform operation to a single item in list
Post by: curmudgeon on July 16, 2009, 04:47:41 PM
Code: [Select]
;; variation by CAB
(defun adjust_nth (opr num lst i)
  (setq i (1+ i))
  (mapcar '(lambda (x) (if (zerop (setq i (1- i))) (opr num x) x)) lst)
)

Code: [Select]
_$ (adjust_nth + 3 '(1 2 3 4 5 6 7) 4)
(1 2 3 4 8 6 7)

man!
that is clean. bravo.
Title: Re: Perform operation to a single item in list
Post by: MP on July 16, 2009, 04:51:04 PM
A different twist on a generic solution, Q+D, coded lean, no error checking etc.

Code: [Select]
(defun ApplyFooToNth ( [color=red]foo[/color] [color=green]n[/color] [color=blue]lst[/color] )
    (   (lambda ( bar i ) (mapcar 'bar lst))
        (lambda ( a )
            (if (eq n (setq i (1+ i)))
                (progn (defun bar (a) a) (foo a))
                a
            )
        )
        -1
    )    
)

Looks verbose but should perform reasonably.

(ApplyFooToNth (lambda (x) (+ 7 x)) 2 '(1 2 3 4 5))

=> (1 2 10 4 5)

Edit: Revised specifically to tease se7en. :)

Title: Re: Perform operation to a single item in list
Post by: Lee Mac on July 16, 2009, 04:57:53 PM
    (defun bar ( a )
        (if (eq n (setq i (+ i j)))
            (progn (defun bar (a) a) (foo a))
            a
        )
    )

I think my head just exploded...   :laugh:

Nice use of colours though  :-)
Title: Re: Perform operation to a single item in list
Post by: JohnK on July 16, 2009, 05:00:47 PM
Binky, where da-hell you been?! Ive tried several times to get a hold of you.
Hows things?
Title: Re: Perform operation to a single item in list
Post by: Lee Mac on July 16, 2009, 05:07:46 PM
Michael,

I see you use that "Double Defun" trick on this code too:

http://www.theswamp.org/index.php?topic=4903.0 (http://www.theswamp.org/index.php?topic=4903.0)  (Great code btw)

But I am having real trouble understanding how it works/is evaluated...

If you have a bit of time, would you be able to shed some light for my confused mind...  :-)

Thanks,

Lee

EDIT: just seen you have an explanation on a few pages later in that thread... never mind - I must be blind
Title: Re: Perform operation to a single item in list
Post by: JohnK on July 16, 2009, 05:10:01 PM
Quote
...(if (eq n (setq i (+ i j)))
            (progn (defun bar (a) a) (foo a))
            a
        )
hehehe ...nice. I could swear, i had used a redefinition (a quine is an exact reproduction but what would this be called?) recently but i cant for the life of me remember where or why.
Title: Re: Perform operation to a single item in list
Post by: VovKa on July 16, 2009, 05:12:17 PM
Michael, you code needs some fixing

(ApplyFooToNth (lambda (x) (+ 7 x)) 0 '(1 2 3 4 5))

=> (1 2 3 4 12)
Title: Re: Perform operation to a single item in list
Post by: MP on July 16, 2009, 05:23:54 PM
You're right vovka, juggling too much here and I combined 2 different approaches. Should have tried it before posting it. :facepalm:

Here's a quick alternate:

Code: [Select]
(defun ApplyFooToNth ( foo n lst / bar )

    (defun bar ( a )
        (if (eq n (setq i (1+ i)))
            (progn (defun bar (a) a) (foo a))
            a
        )
    )
   
    ((lambda (i) (mapcar 'bar lst)) -1)
   
)

(ApplyFooToNth (lambda (x) (+ 7 x)) 0 '(1 2 3 4 5)) => (8 2 3 4 5)

(ApplyFooToNth (lambda (x) (+ 7 x)) 1 '(1 2 3 4 5)) => (1 9 3 4 5)

(ApplyFooToNth (lambda (x) (+ 7 x)) 2 '(1 2 3 4 5)) => (1 2 10 4 5)

(ApplyFooToNth (lambda (x) (+ 7 x)) 3 '(1 2 3 4 5)) => (1 2 3 11 5)

(ApplyFooToNth (lambda (x) (+ 7 x)) 4 '(1 2 3 4 5)) => (1 2 3 4 12)

My apologies peeps and thank you vovka. :)
Title: Re: Perform operation to a single item in list
Post by: ElpanovEvgeniy on July 16, 2009, 05:32:49 PM
my version...
Code: [Select]
(defun f (a b c)
 (cond ((not c) c)
       ((> b 0) (cons (car c) (f a (1- b) (cdr c))))
       (t (cons (a (car c)) (cdr c)))
 ) ;_  cond
)
test:
Code: [Select]
(f (lambda (x) (+ 7 x)) 0 '(1 2 3 4 5)) => (8 2 3 4 5)
(f (lambda (x) (+ 7 x)) 2 '(1 2 3 4 5)) => (1 2 10 4 5)
(f (lambda (x) (+ 7 x)) 5 '(1 2 3 4 5)) => (1 2 3 4 5)
Title: Re: Perform operation to a single item in list
Post by: Binky on July 16, 2009, 10:56:50 PM
OK here is what I think I will end up with, stealing a bit from here and another bit from there.

CAB that was short, sweet and to the point.  Nice!

MP, It took me a minute to see the value of redefining the function once the particular index was reached(never would have thought of that myself, thanks for the enlightenment), as it saves time from having to re-evaluate the test condition after the need for it no longer exists.  That would save time on large lists.

Tim makes a great point about ordering the arguments for readability, I often forget that.

Code: [Select]
(defun nthadjust (opr val pos lst / foo)
  (defun foo (x)
    (if (= pos (setq i (1+ i)))
      (progn
        (defun foo (x) x)
        (opr val x))
      x))

  ((lambda (i) (mapcar 'foo lst)) -1)
)

Thanks everybody
Title: Re: Perform operation to a single item in list
Post by: Keith™ on July 17, 2009, 12:05:56 AM
OK here is what I think I will end up with, stealing a bit from here and another bit from there.

...


that is the point ... we supply various bits of information that you can decide whether it is useful or not, take the good bits, toss the rest ...

We like to think of it as teaching a man to fish (http://www.theswamp.org/index.php?topic=2621.msg33156#msg33156)