Sorting list of lists by 2 values

Discussion in 'AutoCAD' started by Alan Henderson, Mar 2, 2004.

  1. I have gone through all the vl-sort and sort messages and have not been able
    to figure out how to sort a list of lists.
    I have used TonyT's elegant sort program to sort by 1 value, but can't
    figure out how to sort twice.
    ;;slightly modify TonyT's
    (defun NLSORT (OLIST SN / T1 T2)
    (setq NLIST (vl-sort OLIST (function (lambda (T1 T2) (< (atof (nth SN T1))
    (atof (nth SN T2)))))))
    )
    P.S. I would like the program to be able to sort any 2 items in a list that
    can be differing lengths (3-10 items)

    Here is the original list -
    (setq LLIST (list (list "Wire1" 0.625 12.0) (list "Wire2" 0.125 24.0) (list
    "Wire1" 0.625 24.0) (list "Wire2" 0.125 8.0))

    ("Wire1" 0.625 12.0)
    ("Wire2" 0.125 24.0)
    ("Wire1" 0.625 24.0)
    ("Wire2" 0.125 8.0)

    I would like the list sorted by the 1st value in the sublist, then by the
    shortest 3rd value in the sublist
    ("Wire1" 0.625 12.0)
    ("Wire1" 0.625 24.0)
    ("Wire2" 0.125 8.0)
    ("Wire2" 0.125 24.0)

    Thanks in Advance......
     
    Alan Henderson, Mar 2, 2004
    #1
  2. (The 'code block' is so it will look ok web side)

    Code:
    (defun ScenicRouteForIdeasOnly
    
    (  /
    
    ;  local defuns
    
    VL_Sort
    Pad
    Stringify
    StringifyList
    
    ;  local vars
    
    listOriginal
    listSorted
    temp
    len1
    len2
    
    )
    
    ;  original by tony tanzillo (please note
    ;  the name change, i.e. "_" instead of "-")
    
    (defun VL_Sort ( lst func )
    (mapcar
    '(lambda (x) (nth x lst))
    (vl-sort-i lst func)
    )
    )
    
    ;  local defun Pad
    
    (defun Pad ( x len / result)
    (setq result (Stringify x))
    (while (< (strlen result) len)
    (setq result (strcat " " result))
    )
    result
    )
    
    ;  local defun Stringify
    
    (defun Stringify ( x )
    (cond
    ((eq 'str (type x)) x)
    ((numberp x) (if (minusp x) (rtos x 2 8) (strcat "+" (rtos x 2 8))))
    ((null x) nil)
    ((listp x) (mapcar 'Stringify x))
    ((vl-princ-to-string x))
    )
    )
    
    ;  local defun StringifyList
    
    (defun StringifyList ( lst / dimzin result )
    (setq dimzin (getvar "dimzin"))
    (setvar "dimzin" 0)
    (setq result (Stringify lst))
    (setvar "dimzin" dimzin)
    result
    )
    
    ;  our test data
    
    (setq listOriginal
    '(
    ("Wire1" 0.625 24.0)
    ("Wire2" 0.125 24.0)
    ("Wire1" 0.625 12.0)
    ("Wire2" 0.125 8.0)
    )
    )
    
    ;  semi useful prompt
    
    (progn
    (princ "\nOriginal list:\n")
    (mapcar 'print listOriginal)
    )
    
    ;  pre-game warmup ...
    
    (setq
    temp (StringifyList listOriginal)
    len1 (apply 'max (mapcar 'strlen (mapcar 'car temp)))
    len2 (apply 'max (mapcar 'strlen (mapcar 'caddr temp)))
    )
    
    ;  ok, sort it
    
    (setq listSorted
    (vl_sort
    listOriginal
    '(lambda (a b)
    (<
    (strcat
    (pad (car a) len1)
    (pad (caddr a) len2)
    )
    (strcat
    (pad (car b) len1)
    (pad (caddr b) len2)
    )
    )
    )
    )
    )
    
    ;  semi useful prompt
    
    (progn
    (princ "\n\nSorted list:\n")
    (mapcar 'print listSorted)
    )
    
    ;  shhh ...
    
    (princ)
    
    )
    
    Output:
    
    Original list:
    
    ("Wire1" 0.625 24.0)
    ("Wire2" 0.125 24.0)
    ("Wire2" 0.125 8.0)
    ("Wire1" 0.625 12.0)
    
    Sorted list:
    
    ("Wire1" 0.625 12.0)
    ("Wire1" 0.625 24.0)
    ("Wire2" 0.125 8.0)
    ("Wire2" 0.125 24.0)
    
    
    Sorry, I don't have time for an industrial/polished/succinct solution, but this might get
    you started.

    : michael


    I have gone through all the vl-sort and sort messages and have not been able
    to figure out how to sort a list of lists.
    I have used TonyT's elegant sort program to sort by 1 value, but can't
    figure out how to sort twice.
    ;;slightly modify TonyT's
    (defun NLSORT (OLIST SN / T1 T2)
    (setq NLIST (vl-sort OLIST (function (lambda (T1 T2) (< (atof (nth SN T1))
    (atof (nth SN T2)))))))
    )
    P.S. I would like the program to be able to sort any 2 items in a list that
    can be differing lengths (3-10 items)

    Here is the original list -
    (setq LLIST (list (list "Wire1" 0.625 12.0) (list "Wire2" 0.125 24.0) (list
    "Wire1" 0.625 24.0) (list "Wire2" 0.125 8.0))

    ("Wire1" 0.625 12.0)
    ("Wire2" 0.125 24.0)
    ("Wire1" 0.625 24.0)
    ("Wire2" 0.125 8.0)

    I would like the list sorted by the 1st value in the sublist, then by the
    shortest 3rd value in the sublist
    ("Wire1" 0.625 12.0)
    ("Wire1" 0.625 24.0)
    ("Wire2" 0.125 8.0)
    ("Wire2" 0.125 24.0)

    Thanks in Advance......
     
    michael puckett, Mar 2, 2004
    #2
  3. Replace this ...

    Code:
    (defun Stringify ( x )
    (cond
    ((eq 'str (type x)) x)
    ((numberp x) (if (minusp x) (rtos x 2 8) (strcat "+" (rtos x 2 8))))
    ((null x) nil)
    ((listp x) (mapcar 'Stringify x))
    ((vl-princ-to-string x))
    )
    )
    
    .... with this:

    Code:
    (defun Stringify ( x )
    (cond
    ((eq 'str (type x)) x)
    ((numberp x) (if (minusp x) (rtos x 2 8) (strcat "+" (rtos x 2 8))))
    ((null x) "")
    ((listp x) (mapcar 'Stringify x))
    ((vl-princ-to-string x))
    )
    )
    

    <big pile 'o crud snipped ...>
     
    michael puckett, Mar 2, 2004
    #3
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.