Jump to content

Recommended Posts

Posted (edited)

I have a list structure like this:
 

list=((“aa” “A”) (“bb” “B”) (“cc” “A”) (“dd” “C”) (“ee” “D”) (“ff” “B”) (“gg” “C”) (“hh ” “A”)...)

I am struggling over combining 2 different lists with same element, the end result would be something look like this:

result_list=((“aacchh” “A”) (“bbff” “B”)(“ddgg” “C”) (“ee” “D”)...)

I think I need to use the mapcar and lambda function, but just not sure. Any help would be great.

Edited by Hashiq
Posted (edited)

edit: combine sublists with same second element (“A” “B” “C” in this example), forgive my bad English expression. 

Edited by Hashiq
Posted (edited)
(defun C:00	(/ E1 E2 L1 L2 LST L0)
	(setq l0 nil l1 nil l2 nil)
	(setq	lst	(list	'("aa" "A")	'("bb" "B")	'("cc" "A")	'("dd" "C")	'("ee" "D")	'("ff" "B")	'("gg" "C")	'("hh " "A"))
	)
	(setq	l0 (mapcar '(lambda (x) (vl-remove-if '(lambda (y) (/= (cadr y) (cadr x))) lst))
										 (vl-sort lst '(lambda (e1 e2) (< (cadr e1) (cadr e2))))
						 )
	)
	(setq	l1 (mapcar '(lambda	(e1)
											(list (apply 'strcat (mapcar '(lambda (e2) (car e2)) e1)) (cadr (last e1)))
										)
									 l0
					 )
	)
	(setq l2 (LM:UniqueFuzz l1 1e-8))
	(princ l2)
	(princ)
)
(defun LM:UniqueFuzz (l f)
	(if	l
		(cons	(car l)
					(LM:UniqueFuzz
						(vl-remove-if
							(function (lambda (x) (equal x (car l) f)))
							(cdr l)
						)
						f
					)
		)
	)
)

 You try!

Edited by thanhduan2407
  • Agree 1
Posted

You can use following function to get desired result:

(defun foo (l f / r z)
  (foreach x l
    (if	(setq z	(vl-some '(lambda (y)
			    (if	(f x (car y))
			      y
			    )
			  )
			 r
		)
	)
      (setq r (subst (cons x z) z r))
      (setq r (cons (list x) r))
    )
  )
  (reverse (mapcar 'reverse r))
)

(setq lst (mapcar '(lambda (x)
		     (cons (apply 'strcat (mapcar 'car x)) (cadar x))
		   )
		  (foo l (lambda (e1 e2) (equal (cadr e1) (cadr e2))))
	  )
)

 

Result:

_$ (setq l '(("aa" "A") ("bb" "B") ("cc" "A") ("dd" "C") ("ee" "D") ("ff" "B") ("gg" "C") ("hh " "A")))
(("aa" "A") ("bb" "B") ("cc" "A") ("dd" "C") ("ee" "D") ("ff" "B") ("gg" "C") ("hh " "A"))
_$ (setq lst (mapcar '(lambda (x)
		     (cons (apply 'strcat (mapcar 'car x)) (cadar x))
		   )
		  (foo l (lambda (e1 e2) (equal (cadr e1) (cadr e2))))
	  )
)
(("aacchh " . "A") ("bbff" . "B") ("ddgg" . "C") ("ee" . "D"))

 

  • Agree 1
Posted

My attempt. :) 

 

(setq lst '(("aa" "A") ("bb" "B") ("cc" "A") ("dd" "C") ("ee" "D") ("ff" "B") ("gg" "C") ("hh" "A")))

 

Test:

(while lst
  (setq itm (car lst))
  (or (and (vl-some (function (lambda (x) (and (= (cadr itm) (cadr x)) (setq fnd x)))) itms)
           (setq itms (subst (list (strcat (car fnd) (car itm)) (cadr itm)) fnd itms))
           )
      (setq itms (cons itm itms))
      )
  (setq lst (vl-remove itm lst))
  )
(reverse itms)

 

  • Agree 1
Posted
5 hours ago, thanhduan2407 said:

(defun C:00	(/ E1 E2 L1 L2 LST L0)
	(setq l0 nil l1 nil l2 nil)
	(setq	lst	(list	'("aa" "A")	'("bb" "B")	'("cc" "A")	'("dd" "C")	'("ee" "D")	'("ff" "B")	'("gg" "C")	'("hh " "A"))
	)
	(setq	l0 (mapcar '(lambda (x) (vl-remove-if '(lambda (y) (/= (cadr y) (cadr x))) lst))
										 (vl-sort lst '(lambda (e1 e2) (< (cadr e1) (cadr e2))))
						 )
	)
	(setq	l1 (mapcar '(lambda	(e1)
											(list (apply 'strcat (mapcar '(lambda (e2) (car e2)) e1)) (cadr (last e1)))
										)
									 l0
					 )
	)
	(setq l2 (LM:UniqueFuzz l1 1e-8))
	(princ l2)
	(princ)
)
(defun LM:UniqueFuzz (l f)
	(if	l
		(cons	(car l)
					(LM:UniqueFuzz
						(vl-remove-if
							(function (lambda (x) (equal x (car l) f)))
							(cdr l)
						)
						f
					)
		)
	)
)

 You try!

thanhduan2407.

Thank you for  your mapcar & lambda solution, I tried your code and it work great. but there is a little problem i should mention earlier, sometimes, there is a third ( fourth or more ) element within each sublist, like

(("aa" "A" "11") ("bb" "B" "22") ("cc" "A" "33") ("dd" "C" "44") ("ee" "D" "55") ("ff" "B" "66") ("gg" "C" "") ("hh" "A" "88"))

all sublists have the same length,  could we twist this code a little, to combine other elements base on the second element? result something like:

(("aacchh" "A" "113388") ("bbff" "B" "2266")("ddgg" "C" "44") ("ee" "D" "55")

i am thinking about change "(cadr (last e1)" to "(cdr (last e1)" at first, but that does not work.

Posted
4 hours ago, satishrajdev said:

You can use following function to get desired result:


(defun foo (l f / r z)
  (foreach x l
    (if	(setq z	(vl-some '(lambda (y)
			    (if	(f x (car y))
			      y
			    )
			  )
			 r
		)
	)
      (setq r (subst (cons x z) z r))
      (setq r (cons (list x) r))
    )
  )
  (reverse (mapcar 'reverse r))
)

(setq lst (mapcar '(lambda (x)
		     (cons (apply 'strcat (mapcar 'car x)) (cadar x))
		   )
		  (foo l (lambda (e1 e2) (equal (cadr e1) (cadr e2))))
	  )
)

 

Result:


_$ (setq l '(("aa" "A") ("bb" "B") ("cc" "A") ("dd" "C") ("ee" "D") ("ff" "B") ("gg" "C") ("hh " "A")))
(("aa" "A") ("bb" "B") ("cc" "A") ("dd" "C") ("ee" "D") ("ff" "B") ("gg" "C") ("hh " "A"))
_$ (setq lst (mapcar '(lambda (x)
		     (cons (apply 'strcat (mapcar 'car x)) (cadar x))
		   )
		  (foo l (lambda (e1 e2) (equal (cadr e1) (cadr e2))))
	  )
)
(("aacchh " . "A") ("bbff" . "B") ("ddgg" . "C") ("ee" . "D"))

 

satishrajdev

thank you, i have tried your code, and it works, thanks again.

Posted
2 hours ago, Tharwat said:

My attempt. :) 

 


(setq lst '(("aa" "A") ("bb" "B") ("cc" "A") ("dd" "C") ("ee" "D") ("ff" "B") ("gg" "C") ("hh" "A")))

 

Test:


(while lst
  (setq itm (car lst))
  (or (and (vl-some (function (lambda (x) (and (= (cadr itm) (cadr x)) (setq fnd x)))) itms)
           (setq itms (subst (list (strcat (car fnd) (car itm)) (cadr itm)) fnd itms))
           )
      (setq itms (cons itm itms))
      )
  (setq lst (vl-remove itm lst))
  )
(reverse itms)

 

Tharwat,

thanks for your wonderfulI code, I really appreciate your time. Any idea on how to solve the same problem when those sublists contain three or more elements?

Posted
31 minutes ago, Hashiq said:

Tharwat,

thanks for your wonderfulI code, I really appreciate your time. Any idea on how to solve the same problem when those sublists contain three or more elements?

 

You're welcome. :) 

That requires a different go I believe, you can elaborate what you want then me or someone else would try to help you out with it if possible.

Posted (edited)

I apologise, my attempt is very late:

(setq lst '(("aa" "A") ("bb" "B") ("cc" "A") ("dd" "C") ("ee" "D") ("ff" "B") ("gg" "C") ("hh" "A")))

 

Test:

(setq lst (mapcar '(lambda (elem) (reverse elem)) lst))
(setq lst2 "" lst3 '())
(while lst
 (setq elem (caar lst))
 (while (car (assoc elem lst))
  (setq lst2 (strcat lst2 (cadr (assoc elem lst))))
  (setq lst (vl-remove (assoc elem lst) lst))
 )
 (setq lst3 (cons (list elem lst2) lst3))
 (setq lst2 "")
)
(mapcar '(lambda (elem) (reverse elem)) (reverse lst3))

 

Edited by confutatis
Posted

Using Lee's Group By Keys Sub its quite easy:

; https://www.theswamp.org/index.php?topic=53515.0
; Lee Mac 
(defun groupbykey ( lst / rtn tmp )
  (foreach itm (reverse lst)
    (if (setq tmp (assoc (car itm) rtn))
      (setq rtn (subst (vl-list* (car itm) (cdr itm) (cdr tmp)) tmp rtn))
      (setq rtn (cons  (list (car itm) (cdr itm)) rtn))
    )
  )
)

Ofcourse along with the mapcar'n'lambda stuff:

_$ (setq L '(("aa" "A") ("bb" "B") ("cc" "A") ("dd" "C") ("ee" "D") ("ff" "B") ("gg" "C") ("hh " "A")))
(("aa" "A") ("bb" "B") ("cc" "A") ("dd" "C") ("ee" "D") ("ff" "B") ("gg" "C") ("hh " "A"))
_$ (reverse (mapcar '(lambda (x) (cons (apply 'strcat (apply 'append (cdr x))) (car x))) (groupbykey (mapcar 'reverse L))))
(("aacchh " . "A") ("ddgg" . "C") ("bbff" . "B") ("ee" . "D"))

 

Posted
10 hours ago, Grrr said:

Using Lee's Group By Keys Sub its quite easy:

Why do you usually use lee's functions and not try to write yours ?

Would like to see your own attempts. ;) 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...