Add element to list of lists

Add element to list of lists

Browning_Zed
Advocate Advocate
1,240 Views
15 Replies
Message 1 of 16

Add element to list of lists

Browning_Zed
Advocate
Advocate

Dear sirs, help me solve the following problem.


I need a function that would add an item to a list with nested lists.
The original list might look like this:
'((1 3 5) (1 3 5) (1 3 5))

after that I need to insert at position: (nth 1) element "2", and at position: (nth 2) element 4. Then the transformed list will look like this:
'((1 "2" 3 4 5) (1 "2" 3 4 5) (1 "2" 3 4 5))

 

The very execution of the function in this case may look like this:
(somefunction '((1 "2") (2 4)))
The first item is a position on the list, starting from zero.
The second item is the value of the added element.
Theoretically, there can be an unlimited number of added elements, but there should be no more than the length of the original list.
Thanks in advance.

0 Likes
Accepted solutions (3)
1,241 Views
15 Replies
Replies (15)
Message 2 of 16

marko_ribar
Advisor
Advisor
Accepted solution
(defun foo ( addlist reflist / n v r k )
  (setq n (mapcar 'car addlist))
  (setq v (mapcar 'cadr addlist))
  (setq r (mapcar '(lambda ( a ) (setq k -1) (apply 'append (mapcar '(lambda ( b ) (setq k (1+ k)) (if (vl-position k n) (list (nth (vl-position k n) v) b) (list b))) a))) reflist))
  r
)

;;; (foo '((1 "2") (2 4)) '((1 3 5) (1 3 5) (1 3 5))) => ((1 "2" 3 4 5) (1 "2" 3 4 5) (1 "2" 3 4 5))
Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 3 of 16

Browning_Zed
Advocate
Advocate
Thanks for your help.
0 Likes
Message 4 of 16

Browning_Zed
Advocate
Advocate

Again I ask you for help. Is it possible to modify the function to be able to add a nil value?
For example:
;;; (foo '((1 nil))' ((1 3 5) (1 3 5) (1 3 5))) => ((1 nil 3 5) (1 nil 3 5) (1 nil 3 5))

0 Likes
Message 5 of 16

pbejse
Mentor
Mentor

@Browning_Zed wrote:

The very execution of the function in this case may look like this:
(somefunction '((1 "2") (2 4)))


The target order is based on the orignal order YES?  to clarify, what would be value if you target the two

'((0 "2") (1 4)) 

'((0 "2") (3 4)) 

if the list'((1 3 5) (1 3 5) (1 3 5))

 

BTW: where did you come with al this conditions?

0 Likes
Message 6 of 16

Browning_Zed
Advocate
Advocate

Right. The target order is based on the orignal order.

'((1 3 5) (1 3 5) (1 3 5))

 

'((0 "2") (1 4))
=>> '(("2" 1 4 3 5) ("2" 1 4 3 5) ("2" 1 4 3 5))

'((0 "2") (3 4))
=>> '(("2" 1 3 5) ("2" 1 3 5) ("2" 1 3 5))

'((0 "2") (3 3))
=>> '(("2" 1 3 5 3) ("2" 1 3 5 3) ("2" 1 3 5 3))

 

Well, I need to redirect lists to specific functions that expect a specific number of items. And in my case, the best way is to transform the list.😏

0 Likes
Message 7 of 16

pbejse
Mentor
Mentor

@Browning_Zed wrote:

Right. The target order is based on the orignal order.

Well, I need to redirect lists to specific functions that expect a specific number of items. And in my case, the best way is to transform the list.😏


That does not answer my question @Browning_Zed.

I need you to confirm what is the correct value of the list if your input is '((0 "2") (1 4))

is it  (("2" 4 1 3 5) ("2" 4 1 3 5) ("2" 4 1 3 5))  at position 0 and 1 ?

 

Based on your edited post

Where is 4 in this result?

'((0 "2") (3 4))
=>> '(("2" 1 3 5) ("2" 1 3 5) ("2" 1 3 5))

Are you sure THAT is the correct value?

 

 

 

0 Likes
Message 8 of 16

Browning_Zed
Advocate
Advocate

Sorry, I was wrong. It should be like this:
'((0 "2") (3 4))
= >> '(("2" 1 3 5 4) ("2" 1 3 5 4) ("2" 1 3 5 4))
'((0 "2") (4 4))
= >> '(("2" 1 3 5) ("2" 1 3 5) ("2" 1 3 5))

0 Likes
Message 9 of 16

ВeekeeCZ
Consultant
Consultant
Accepted solution

Try this generic one. 

 

 ; order list rules: index starts from 1. Negative from add list, positive from sub-lst

(defun add2lst (add lst ord)
  (mapcar '(lambda (sub) (mapcar '(lambda (o) (nth (1- (abs o)) (if (minusp o) add sub))) ord)) lst))				      

(add2lst
  '("2" 4)
  '((1 3 5) (1 3 5) (1 3 5))
  '(1 -1 2 -2 3)
  )

 

Message 10 of 16

pbejse
Mentor
Mentor

@Browning_Zed wrote:

Sorry, I was wrong. It should be like this:
'((0 "2") (3 4))
= >> '(("2" 1 3 5 4) ("2" 1 3 5 4) ("2" 1 3 5 4))


Are you sure this time?

The post you mark as "Solution" shows another result otherwise

 

(FOO '((0 "2") (3 4)) '((1 3 5) (1 3 5) (1 3 5)))
(("2" 1 3 5) ("2" 1 3 5) ("2" 1 3 5))

 

 


@Browning_Zed wrote:

'((0 "2") (4 4))
= >> '(("2" 1 3 5) ("2" 1 3 5) ("2" 1 3 5))


Again, Are you sure about that?

 

0 Likes
Message 11 of 16

Browning_Zed
Advocate
Advocate

((1 3 5))

(( "0 position" 1 "1 position" 3 "2 position"  5 "3 position"))

 

 

0 Likes
Message 12 of 16

pbejse
Mentor
Mentor

@Browning_Zed wrote:

((1 3 5))

(( "0 position" 1 "1 position" 3 "2 position"  5 "3 position"))


The reason why i'm asking is the results i'm getting from following the original logic is inconsistent from your answer.

I just need you to be sure.

There's nothing more frustating to realize at the end the result is not what it's supposed to be.

 

Happy coding

 

0 Likes
Message 13 of 16

Browning_Zed
Advocate
Advocate

Is it possible to modify your function by adding the remove item as well?

0 Likes
Message 14 of 16

ВeekeeCZ
Consultant
Consultant

Why, the current one is good enough.

 

(add2lst
nil
'((1 2 3 4) (1 2 3 4) (1 2 3 4))
'(1 4)
)

Message 15 of 16

pbejse
Mentor
Mentor
Accepted solution

@Browning_Zed wrote:

'((0 "2") (1 4))
=>> '(("2" 1 4 3 5) ("2" 1 4 3 5) ("2" 1 4 3 5))

'((0 "2") (3 4))
=>> '(("2" 1 3 5 4) ("2" 1 3 5 4) ("2" 1 3 5 4))

'((0 "2") (3 3))
=>> '(("2" 1 3 5 3) ("2" 1 3 5 3) ("2" 1 3 5 3))


 

 

Following the same logic

(defun _InsertnAt ( al lst / ord )
(setq ord al)  
	(mapcar '(lambda (v / nl)  
		(repeat (setq n (length v))
		  	(if (setq f (assoc (setq n (1- n)) al))
			  	(setq nl (cons (nth n v) nl)
				      nl (cons (cadr f) nl) al (vl-remove f al))
			  	(setq nl (cons (nth n v) nl))
					  )
				  )
		   (cond
		     ((null al) (setq al ord)  nl)
		     ((setq nl (append nl (mapcar 'cadr al)) al ord) nl))
			)
		lst)
	  )

 

 

(setq lst '((1 3 5) (1 3 5 6 7 8 9) ("A" "B")))
(_InsertnAt '((1 "2") (2 4)) lst) =>> ((1 "2" 3 4 5) (1 "2" 3 4 5 6 7 8 9) ("A" "2" "B" 4)) (_InsertnAt '((0 "2") (1 4)) lst) =>> (("2" 1 4 3 5) ("2" 1 4 3 5 6 7 8 9) ("2" "A" 4 "B")) (_InsertnAt '((0 "2") (3 4)) lst) =>> (("2" 1 3 5 4) ("2" 1 3 5 4 6 7 8 9) ("2" "A" "B" 4)) (_InsertnAt '((0 "2") (3 3)) lst) =>> (("2" 1 3 5 3) ("2" 1 3 5 3 6 7 8 9) ("2" "A" "B" 3)) (_InsertnAt '((0 "2") (3 3)(4 "Uppity)) lst) =>> (("2" 1 3 5 3 "Uppity) ("2" 1 3 5 3 6 "Uppity" 7 8 9) ("2" "A" "B" 3 "Uppity))

-------------------------------------------------------------------------------------------- (_InsertnAt '((0 "2") (3 "LSP")(4 "pBe")) '((1 3 5) (1 3 5 6 7 8 9) ("A" "B" "C" "D"))) =>> (("2" 1 3 5 "LSP" "pBe") ("2" 1 3 5 "LSP" 6 "pBe" 7 8 9) ("2" "A" "B" "C" "LSP" "D" "pBe"))

(1 3 5) <-- beyond number of items ("2" 1 3 5 "LSP" "pBe")
(1 3 5 6 7 8 9) <-- enough to cover additional items <-- ("2" 1 3 5 "LSP" 6 "pBe" 7 8 9)
("A" "B")<-- enough to cover additional items ("2" "A" "B" "C" "LSP" "D" "pBe"))

 

0 Likes
Message 16 of 16

pbejse
Mentor
Mentor

If you  want to exclude the items out of range of the target list

 

(defun _InsertnAtnil ( al lst )
	(mapcar '(lambda (v / nl)  
		(repeat (setq n (length v))
		  	(if (setq f (assoc (setq n (1- n)) al))
			  	(setq nl (cons (nth n v) nl)
				      nl (cons (cadr f) nl))
			  	(setq nl (cons (nth n v) nl))
					  )
				  )		   
			)
		lst)
	  )

 

(_InsertnAtnil '((0 "2") (3 "LSP")(4 "pBe")) '((1 3 5) (1 3 5 6 7 8 9) ("A" "B" "C" "D"))) 
(("2" 1 3 5) ("2" 1 3 5 "LSP" 6 "pBe" 7 8 9) ("2" "A" "B" "C" "LSP" "D"))