Author Topic: Sorting using more criteria?  (Read 2634 times)

0 Members and 1 Guest are viewing this topic.

kruuger

  • Swamp Rat
  • Posts: 635
Sorting using more criteria?
« on: September 09, 2016, 02:46:26 AM »
hello
how to sort list using 2,3 or more criteria?
for example in attached file was first column (floor number). then in in each floor sort using second floor - room number and then third if we want etc
hope i'm clear.
thanks
kruuger

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Sorting using more criteria?
« Reply #1 on: September 09, 2016, 02:55:45 AM »
Code: [Select]
(vl-sort
    (list (list 1 2 5 3) (list 1 2 3 4))
    (function
        (lambda ( a b )
            (while (equal (car a) (car b))
                (setq a (cdr a))
                (setq b (cdr b))
            )
            (< (car a) (car b))
        )
    )
)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Sorting using more criteria?
« Reply #2 on: September 09, 2016, 03:07:14 AM »
Code: [Select]
...
            (while (equal (car a) (car b))
...
Just be careful there:
(equal nil nil) --> true


Infinite loop?
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Sorting using more criteria?
« Reply #3 on: September 09, 2016, 03:48:07 AM »
My suggestion ... allows for unequal lengths and duplicates:
Code: [Select]
(defun compare-lists (a b)
  (cond ((not a))
((not b) nil)
((< (car a) (car b)))
((equal (car a) (car b))
(compare-lists (cdr a) (cdr b)))
(t nil)))


(defun sort-list (lst / )
  (vl-sort lst 'compare-lists))
Using recursion to check following items in lists.

Sample run:
Code: [Select]
_$ (sort-list '((1 2 5 3) (1 2 3 4) (1 7 3) (1 7 3 4) (1 2 5 3) (1 1 4 5) (1 1 4 2)))
((1 1 4 2) (1 1 4 5) (1 2 3 4) (1 2 5 3) (1 2 5 3) (1 7 3) (1 7 3 4))

Of course be warned there's a possibility of errors due to comparing different types. E.g. an integer compared to a string would cause an error.
« Last Edit: September 09, 2016, 03:51:17 AM by irneb »
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

kruuger

  • Swamp Rat
  • Posts: 635
Re: Sorting using more criteria?
« Reply #4 on: September 09, 2016, 03:36:34 PM »

irneb, looks like your code works very well with my list :)
thank you for both of you.
kruuger

kruuger

  • Swamp Rat
  • Posts: 635
Re: Sorting using more criteria?
« Reply #5 on: November 25, 2016, 07:04:55 AM »
ehh this sorting stuff is over my head :(
i have a gile routines (attached file) for architectural sort and would like use it in irneb or Tim code.
Can this be easily incorporate?

sample list can be:
Code: [Select]
(setq a (list '("100" "ba" 10) '("100" "ab" 12) '("23" "de" 4) '("88" "we" '("1234" "ps" 1) '("1234" "cd" 2)))if i'm correct result should be
Code: [Select]
("23" "de" 4) ("88" "we" ("100" "ab" 12) ("100" "ba" 10) ("1234" "cd" 2) ("1234" "ps" 1)

thanks
thanks

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Sorting using more criteria?
« Reply #6 on: November 25, 2016, 08:29:31 AM »
Assuming your list should actually be something like:
Code - Auto/Visual Lisp: [Select]
  1. (list '("100" "ba" 10) '("100" "ab" 12) '("23" "de" 4) '("88" "we" 3) '("1234" "ps" 1) '("1234" "cd" 2))

Try the following:
Code - Auto/Visual Lisp: [Select]
  1. (defun mysort ( lst )
  2.     (vl-sort lst
  3.         (function
  4.             (lambda ( a b )
  5.                 (apply
  6.                    '(lambda ( x y )
  7.                         (cond
  8.                             (   (null x))
  9.                             (   (null y) nil)
  10.                             (   (and (= 'str (type x)) (= 'str (type y)))
  11.                                 (alphanumcompare x y)
  12.                             )
  13.                             (   (= 'str (type x)))
  14.                         )
  15.                     )
  16.                     (listmismatch a b)
  17.                 )
  18.             )
  19.         )
  20.     )
  21. )
  22. (defun alphanumcompare ( a b )
  23.     (apply
  24.        '(lambda ( a b / x y )
  25.             (apply
  26.                '(lambda ( x y )
  27.                     (cond
  28.                         (   (null x))
  29.                         (   (null y) nil)
  30.                         (   (and (numberp x) (numberp y)) (< x y))
  31.                         (   (numberp x))
  32.                         (   (numberp y) nil)
  33.                         (   (< x y))
  34.                     )
  35.                 )
  36.                 (listmismatch a b)
  37.             )
  38.         )
  39.         (mapcar 'LM:splitstring (list a b))
  40.    )
  41. )
  42. (defun listmismatch ( a b / x y )
  43.     (while
  44.         (and
  45.             (setq x (car a))
  46.             (setq y (car b))
  47.             (= x y)
  48.         )
  49.         (setq a (cdr a)
  50.               b (cdr b)
  51.         )
  52.     )
  53.     (list x y)
  54. )
  55.  
  56. ;; Split String  -  Lee Mac
  57. ;; Splits a string into a list of text and numbers
  58.  
  59. (defun LM:splitstring ( str )
  60.     (
  61.         (lambda ( l )
  62.             (read
  63.                 (strcat "("
  64.                     (vl-list->string
  65.                         (apply 'append
  66.                             (mapcar
  67.                                 (function
  68.                                     (lambda ( a b c )
  69.                                         (cond
  70.                                             (   (or (= 34 b) (= 92 b))
  71.                                                 (list 32 34 92 b 34 32)
  72.                                             )
  73.                                             (   (or (< 47 b 58)
  74.                                                    ;(and (= 45 b) (< 47 c 58) (not (< 47 a 58)))
  75.                                                     (and (= 46 b) (< 47 a 58) (< 47 c 58))
  76.                                                 )
  77.                                                 (list b)
  78.                                             )
  79.                                             (   (list 32 34 b 34 32))
  80.                                         )
  81.                                     )
  82.                                 )
  83.                                 (cons nil l) l (append (cdr l) '(( )))
  84.                             )
  85.                         )
  86.                     )
  87.                     ")"
  88.                 )
  89.             )
  90.         )
  91.         (vl-string->list str)
  92.     )
  93. )
Example:
Code - Auto/Visual Lisp: [Select]
  1. _$ (mysort (list '("100" "ba" 10) '("100" "ab" 12) '("23" "de" 4) '("88" "we" 3) '("1234" "ps" 1) '("1234" "cd" 2)))
  2. (("23" "de" 4) ("88" "we" 3) ("100" "ab" 12) ("100" "ba" 10) ("1234" "cd" 2) ("1234" "ps" 1))

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Sorting using more criteria?
« Reply #7 on: November 25, 2016, 08:56:21 AM »
Another way to skin the cat ...

If we assume this is your actual data:

Code: [Select]
(setq lst
   '(
        ("100"  "ba" 10)
        ("100"  "ab" 12)
        ("23"   "de" 4)
        ("88"   "we" 3)
        ("1234" "ps" 1)
        ("1234" "cd" 2)
    )   
)

Then constructing, using, and then discarding a temporary sort key can often be significantly faster than ambitious tiered sorting algorithms (tho not nearly as elegant).

Quick and dirty example:

Code: [Select]
(defun foo ( lst )
    (   (lambda ( n f ) (mapcar 'f lst))
        (apply 'max (mapcar 'strlen lst))
        (lambda (s) (while (< (strlen s) n) (setq s (strcat "0" s))) s)
    )       
)

(defun bar ( lst )
    (foo (mapcar 'itoa lst))
)

(mapcar 'cdr
    (vl-sort
        (mapcar
            (function (lambda (a b c d) (cons (strcat a b c) d)))   
            (foo (mapcar 'car lst))
            (foo (mapcar 'cadr lst))
            (bar (mapcar 'caddr lst))
            lst
        )
        (function (lambda (a b) (< (car a) (car b))))
    )
)

Result:

(   ("23" "de" 4)
    ("88" "we" 3)
    ("100" "ab" 12)
    ("100" "ba" 10)
    ("1234" "cd" 2)
    ("1234" "ps" 1)
)


Cheers.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

kruuger

  • Swamp Rat
  • Posts: 635
Re: Sorting using more criteria?
« Reply #8 on: November 25, 2016, 09:38:45 AM »
my bad  :oops:   first item on the list is a room name, so can be 100A, 120AB, 100AA (with letters)
more crazy list. not sure if covered all possible numbers but it is hard to predict architect fancy numbering system

Code: [Select]
(setq lst
   '(
        ("100B"  "ba" 10)
        ("88"   "we.F" 23)
        ("001" "123a" 23)
        ("001" "43a" 23)
        ("00043" "bb" 23)
        ("00043c" "aaa" 23)
        ("02" "WWW" 23)
        ("2A" "AA" 23)
        ("100A"  "ab" 12)
        ("23"   "de" 4)
        ("43"   "we.A" 23)
        ("1A" "AS" 23)
        ("88"   "we.C" 23)
        ("1234" "ps" 1)
        ("1234" "cd" 2)
        ("100"  "Xab" 12)
        ("00001" "a" 23)
        ("100AA"  "Xab" 12)
    )   
)


even with that Lee code handle this:
Code: [Select]
("00001" "a" 23)
("001" "43a" 23)
("001" "123a" 23)
("1A" "AS" 23)
("02" "WWW" 23)
("2A" "AA" 23)
("23" "de" 4)
("43" "we.A" 23)
("00043" "bb" 23)
("00043c" "aaa" 23)
("88" "we.C" 23)
("88" "we.F" 23)
("100" "Xab" 12)
("100A" "ab" 12)
("100AA" "Xab" 12)
("100B" "ba" 10)
("1234" "cd" 2)
("1234" "ps" 1))


need to try this on new project.
not sure if i'm able understand your magic :(


thanks guys