Code Red > AutoLISP (Vanilla / Visual)

How to substitute some item in different depth list

(1/4) > >>

qjchen:
How to substitute some item in different depth list

In Lisp, the list is very useful, it is more  flexible  than the ordinary array in other Language such as

Fortran or Basic.
But when I translate some other Language to Lisp, I am always confuse of how to deal with the

translation between array and list.
For example,

A=[ x y z ....]
B=[[a1 b1 c1][a2 b2 c2][.........]]
C=[ [[x1 y1 z1][x2 y2 z2]] [[x3 y3 z3][x4 y4 z4]] [...]]

In other Language, we often get the value of a array by:
Value=A[5] or B[6,5] or C[3,4,5]

or put the value by:
 A[5] or B[6,5] or C[3,4,5]=Value

but in Lisp, I found it is not so easy
when get a value is easlier, we should use (nth (nth (nth ))),
but when put a value, it is trouble, maybe we can write a function, such as SUBSTI(new position

list) to substitute, but when the list is multi-depth, such as B or C or more deep list. Maybe we

should write several defun to adapt the different situation.

Because many scientific code are written by other Language, sometimes I need to translate it to

Lisp, for example, inverse matrix,  I am not familar with safearray in vlisp and hope it could be

done by Lisp.
so my question is: How can we write a more general function to substitute the item in the list

with multi-depth, no matter how deep the list is.
For example, we can
PUT(C, 1,2,3, z2a) to substitute the z2 in C
PUT(B, 2,2,b2a) to substitute the b2 to b2a in B

GET(B, 2,2) to get the value of b2, and GET(A,3) to get the value of z

Maybe I get a wrong way of the problem, Maybe it is easy, but I hope you could help me.

Kerry:
not the most elegant or efficient, but ..
Have a look at nth


--- Code: ---
(SETQ b (LIST (LIST 1 2 3) (LIST 4 5 6) (LIST 7 8 9)))

;;=> ((1 2 3) (4 5 6) (7 8 9))

;;; note .. nth is zero based ....
(SETQ index 2
      step 1
)


(SETQ xx (NTH step (NTH index b)))

;; => returns 8

--- End code ---

qjchen:
thanks kerry

nth is the way to read the list, I define the following code to read the depth=2 list's element, but when the depth is larger than 2, the function have to be rewrote, so I hope a better way to deal it. especially the put value function.


--- Code: ---(defun [n,m] (a n m / i)      
 (setq i (nth (1- m) (nth (1- n) a)))
  i
)

--- End code ---

(SETQ b (LIST (LIST 1 2 3) (LIST 4 5 6) (LIST 7 8 9)))
-----> b  ((1 2 3) (4 5 6) (7 8 9))
([n,m] b 3 2)
----->8

CAB:
Here is my take on the problem.

--- Code: ---(defun c:test ()
  ;;   array structure
  ;;  (list z0(list y0(list x0 x1 x2 x3) y1(list x0 x1 x2 x3) y2(list x0 x1 x2 x3) y3(list x0 x1 x2 x3))
  ;;        z1(list y0(list x0 x1 x2 x3) y1(list x0 x1 x2 x3) y2(list x0 x1 x2 x3) y3(list x0 x1 x2 x3))
  ;;        z2(list y0(list x0 x1 x2 x3) y1(list x0 x1 x2 x3) y2(list x0 x1 x2 x3) y3(list x0 x1 x2 x3))
  ;;  )

  (setq array '((("1" "2" "A" "B") ("C" "D" "E" "F") ("G" "H" "I" "J") ("K" "L" "M" "N"))
                (("O" "P" "Q" "R") ("S" "T" "U" "V") ("W" "X" "Y" "Z") ("a" "b" "c" "d"))
                (("e" "f" "g" "h") ("i" "j" "k" "l") ("m" "n" "o" "p") ("q" "r" "s" "t"))
               )
  )

  (setq x 3
        y 1
        z 2
  )
  (print (setq target (get_itm x y z array)))

  (setq array (substu_array "XX" x y z array))
  (print array)
  (princ)
)
--- End code ---



--- Code: ---(defun get_itm (x y z array)
  (nth x (nth y (nth z array)))
)
--- End code ---



--- Code: ---(defun substu_array (newitm x y z array)
  (subst
    (subst
      (subst newitm (nth x (nth y (nth z array))) (nth y (nth z array)))
      (nth y (nth z array))
      (nth z array)
    )
    (nth z array)
    array
  )
)
--- End code ---

Good night all :)

qjchen:
Thank you, CAB, good code.

It seems that subst is substitute- olditem to newitem, so when the element is duplicate, it get wrong.

(setq array '((("1" "2" "A" "B") ("C" "D" "E" "F") ("G" "H" "I" "J") ("K" "L" "M" "N"))
                (("O" "P" "Q" "R") ("S" "T" "U" "V") ("W" "X" "Y" "Z") ("a" "b" "c" "d"))
                (("e" "f" "g" "h") ("l" "j" "k" "l") ("m" "n" "o" "p") ("q" "r" "s" "t"))
               )
  )

after test, it become:
((("1" "2" "A" "B") ("C" "D" "E" "F") ("G" "H" "I" "J") ("K" "L" "M" "N"))
(("O" "P" "Q" "R") ("S" "T" "U" "V") ("W" "X" "Y" "Z") ("a" "b" "c" "d")) (("e"
"f" "g" "h") ("XX" "j" "k" "XX") ("m" "n" "o" "p") ("q" "r" "s" "t")))


I have wrote a function, it deal with the 2 dimension change, but just like your code, When the array depth of the array is different, the function will be rewrite,
Is it possible to define a function about

FUNC( list_to_be_change, newvalue, position_list)
The position_list is a list that in change one
such as (7) for one dimension array, (3,4) for two dimension array, (3,4,5,6,7,8) for n dimension array

so, when the depth of the array change, the function can be also use.

I think maybe repeat or foreach should be use, but still in confuse. I didnt think it through yet.

my code, reference stdlib

--- Code: ---;;;test function
(defun c:test()
(setq array '((("1" "2" "A" "B") ("C" "D" "E" "F") ("G" "H" "I" "J") ("K" "L" "M" "N"))
                (("O" "P" "Q" "R") ("S" "T" "U" "V") ("W" "X" "Y" "Z") ("a" "b" "c" "d"))
                (("e" "f" "g" "h") ("e" "f" "g" "h") ("m" "n" "o" "p") ("q" "r" "s" "t"))
               )
)
(setq array (qj-setnmth '("l" "j" "k" "XX") 3 2 array))
)


;The stdlib function
(defun std-%setnth (new i lst / fst len)
  (cond
    ((minusp i)
      lst
    )
    ((> i (setq len (length lst)))
      lst
    )
    ((> i (/ len 2))
      (reverse (std-%setnth new (1- (- len i)) (reverse lst)))
    )
    (t
      (append
(progn
  (setq fst nil)        ; ; possible vl lsa compiler bug
  (repeat (rem i 4)
    (setq fst (cons (car lst) fst)
  lst (cdr lst)
    )
  )
  (repeat (/ i 4)
    (setq fst (cons (cadddr lst) (cons (caddr lst) (cons
(cadr lst)
(cons
       (car lst)
       fst
)
   )
)
      )
  lst (cddddr lst)
    )
  )
  (reverse fst)
)
(if (listp new)
  new
  (list new)
)        ; v0.4001
(cdr lst)
      )
    )
  )
)
(defun std-setnth (new i lst)
  (std-%setnth (list new) i lst)
)


;;;substitute the 2 dimension list's i and j element(i and j start from 1)
(defun qj-setnmth (new i j lst / listb lista)
  (setq listb lst)
  (setq i (1- i))
  (setq j (1- j))
  (setq lista (nth i lst))
  (setq lista (std-setnth new j lista))
  (setq listb (std-setnth lista i listb))
  listb
)

--- End code ---


((("1" "2" "A" "B") ("C" "D" "E" "F") ("G" "H" "I" "J") ("K" "L"
"M" "N")) (("O" "P" "Q" "R") ("S" "T" "U" "V") ("W" "X" "Y" "Z") ("a" "b" "c"
"d")) (("e" "f" "g" "h") ("l" "j" "k" "XX") ("m" "n" "o" "p") ("q" "r" "s"
"t")))

Navigation

[0] Message Index

[#] Next page

Go to full version