Author Topic: Sort into Buckets!  (Read 1508 times)

0 Members and 1 Guest are viewing this topic.

zoltan

  • Guest
Sort into Buckets!
« on: December 30, 2008, 04:25:44 PM »
Here is a function I came up with after realizing that this is something I routinely have to do in code with many different conditions.

It takes a list of elements and categorizes them into list of elements that have the have result of a test function.  The syntax is the same as the VL-Sort function.

Code: [Select]
(Defun Categorize ( LST FUNK / lstSubList lstReturn)
 (ForEach atm LST
  (If (SetQ lstSubList (Car (VL-Member-If (Function (Lambda (l) (Eq (Apply FUNK (List atm)) (Apply FUNK (List (Car l)))))) lstReturn)))
   (SetQ lstReturn (Subst (Reverse (Cons atm (Reverse lstSublist))) lstSubList lstReturn) )
   (SetQ lstReturn (Reverse (Cons (List atm) (Reverse lstReturn))) )
  )
 )

 lstReturn
)

For example, you could sort a list of number based on how they are divisible by a number:
_$ (Categorize (List 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) (Function (Lambda (l) (Fix (/ l 5.0)))) )
((1 2 3 4) (5 6 7 8 9) (10 11 12 13 14) (15))
_$

You could sort a list of entities by their layer or other property:
(Categorize lstEnts (Function (Lambda (l) (Cdr (Assoc 8 (EntGet l))))) )


It's not very efficient since it runs the test function a lot and also suffers from the double reverse that is required to get the output lists in somewhat the same order as the input list.  I guess if you were not concerned with the order of the output, you could lose the Reverse calls.  To speed things up, I was thinking about having it cache a list of results that it could test each element against instead of running the test function through the return list every time.  Also, some lisp purist could come up with a way to do it in classic lisp without the use of the VL-Member-If.

See what you think.