Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Sorting a list of lists

2 REPLIES 2
Reply
Message 1 of 3
Anonymous
347 Views, 2 Replies

Sorting a list of lists

Hello,

 

I got a situation when developing some routines with lists. I tried to solve it, but I couldn’t do it for several days. For example, there are some lists like below;

 

(((a b) (1 2 3)) ((c d) (1 2 3)) ((e f) (4 5 6)) ((g h) (1 2 3)) ((i j) (7 8 9 10)) ((k l) (1 2 3 4 5)) ...)

 

I want to get results with each frequency of second lists like below;

 

result1 : (((1 2 3) 3) ((4 5 6) 1) ((1 2 3 4 5) 1)...)

result2 : (((a b) (1 2 3)) ((c d) (1 2 3)) ((g h) (1 2 3)))

 

Sorting the lists are the most biggest challenge of my new geometric sover.

 

Thanks in advance.

 

 

2 REPLIES 2
Message 2 of 3
_gile
in reply to: Anonymous

Hi

 

For result1, you can use the following generic CountBy function

;; gc:CountBy
;; Counts the items of a list by the key generated by the specified function.
;; Returns a list of dotted pairs in which the first item is the key and the second the number of occurences.
;;
;; Arguments
;; fun : the key generator function
;; lst : the list to process
(defun gc:CountBy (fun lst / key pair res)
  (setq fun (eval fun))
  (foreach l lst
    (setq key (fun l)
	  res
	      (if (setq pair (assoc key res))
		(subst (cons key (1+ (cdr pair))) pair res)
		(cons (cons key 1) res)
	      )
    )
  )
)

(gc:CountBy 'cadr '(((a b) (1 2 3)) ((c d) (1 2 3)) ((e f) (4 5 6)) ((g h) (1 2 3)) ((i j) (7 8 9 10)) ((k l) (1 2 3 4 5))))

returns: (((1 2 3 4 5) . 1) ((7 8 9 10) . 1) ((4 5 6) . 1) ((1 2 3) . 3))

 

 

For result2, you can have a look at the vl-remove-if(-not) function.

(vl-remove-if-not
  '(lambda (x) (equal (cadr x) '(1 2 3)))
  '(((a b) (1 2 3)) ((c d) (1 2 3)) ((e f) (4 5 6)) ((g h) (1 2 3)) ((i j) (7 8 9 10)) ((k l) (1 2 3 4 5)))
)

returns: (((A B) (1 2 3)) ((C D) (1 2 3)) ((G H) (1 2 3)))

 

Or, use the following generic GroupBy function and deal with the returned list

;; Groups the items of a list by the key generated by the specified function.
;; Returns a list of lists in which the first item is the key.
;;
;; Arguments
;; fun : the key generator function
;; lst : the list to process
(defun gc:GroupBy (fun lst / key sub res)
  (setq fun (eval fun))
  (mapcar
    '(lambda (l) (cons (car l) (reverse (cdr l))))
    (foreach l lst
      (setq res
	     (if (setq sub (assoc (setq key (fun l)) res))
	       (subst (vl-list* key l (cdr sub)) sub res)
	       (cons (list key l) res)
	     )
      )
    )
  )
)

 (setq groupedList (gc:GroupBy 'cadr '(((a b) (1 2 3)) ((c d) (1 2 3)) ((e f) (4 5 6)) ((g h) (1 2 3)) ((i j) (7 8 9 10)) ((k l) (1 2 3 4 5)))))

returns:

(
  ((1 2 3 4 5) ((K L) (1 2 3 4 5)))
  ((7 8 9 10) ((I J) (7 8 9 10)))
  ((4 5 6) ((E F) (4 5 6)))
  ((1 2 3) ((A B) (1 2 3)) ((C D) (1 2 3)) ((G H) (1 2 3)))
)

 

You can also get result1 from the list returned by gc:GroupBy:

(setq result1 (mapcar '(lambda (x) (cons (car x) (length (cdr x)))) groupedList))



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 3
Anonymous
in reply to: _gile

Fantastic! Man! 🙂 It looks pretty simple, but what I was doing? Thanks for the biggest help.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost