Author Topic: Sort List retrieved from vl-file-systime  (Read 3647 times)

0 Members and 1 Guest are viewing this topic.

Lee Mac

  • Seagull
  • Posts: 12921
  • London, England
Sort List retrieved from vl-file-systime
« on: July 17, 2009, 08:14:15 AM »
Hi Guys,

I am writing a LISP to deal with multiple drawings, and it requires me to find the most recent drawing. Hence I am using vl-file-systime to get the last modified time of each drawing in a directory.

I have compiled a list of drawing names and their respective modification times, and now need to sort the list.

I have used a form of "remove_nth" to remove the day-of-the-week number from the list, as this is unnecessary for this sort.

The list looks something like this:

Code: [Select]
'(("Drawing1" (1998 4 8 10 6 52)) ("Drawing2" (1999 5 4 3 4 12))... etc)

I have created this code to sort it, but I wondered if anyone had anything better - call it a challenge if you will..  :-P

Code: [Select]
(defun dSort (lst / lst)
  (while
    (progn
      (cond ((not
               (vl-remove-if 'null
                 (mapcar 'cadr lst)))
             (setq lst nil))
            ((apply '=
               (vl-sort
                 (mapcar 'caadr lst)
                   (function
                     (lambda (a b) (< a b)))))
             (setq lst (mapcar
                         (function
                           (lambda (x)
                             (list (car x) (cdadr x)))) lst)))
            (t (setq lst (caar lst)) nil))))
  lst)

The above will (or rather "should") return the name of the most recent drawing.

Lee
« Last Edit: July 17, 2009, 10:45:07 AM by Lee Mac »

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Sort List retrieved from vla-file-systime
« Reply #1 on: July 17, 2009, 10:03:19 AM »
Another way.

vl-file-systime Return Values:
              year
   month
   day-of-week   <---  ignore
   day-of-month
   hours
   minutes
   seconds

If not equal sort on year
else if not equal sort on month
else if not equal sort on day-of-month
else if not equal sort on hours
else if not equal sort on minutes
else if not equal sort on seconds




Code: [Select]
(defun sort_systime (lst)
  (vl-sort lst
           '(lambda (e1 e2)
              (cond
                ((/= (caadr e1) (caadr e2)) (< (caadr e1) (caadr e2)))
                ((/= (cadadr e1) (cadadr e2)) (< (cadadr e1) (cadadr e2)))
                ((/= (nth 3 (cadr e1)) (nth 3 (cadr e2)))
                 (< (nth 3 (cadr e1)) (nth 3 (cadr e2))))
                ((/= (nth 4 (cadr e1)) (nth 4 (cadr e2)))
                 (< (nth 4 (cadr e1)) (nth 4 (cadr e2))))
                ((/= (nth 5 (cadr e1)) (nth 5 (cadr e2)))
                 (< (nth 5 (cadr e1)) (nth 5 (cadr e2))))
                ((/= (nth 6 (cadr e1)) (nth 6 (cadr e2)))
                 (< (nth 6 (cadr e1)) (nth 6 (cadr e2))))
              )
            )
  )
)


Code: [Select]
(defun c:test ()
  (mapcar
    'print
    (sort_systime
      '(("Drawing1" (2001 4 8 10 6 52))
        ("Drawing2" (1999 5 4 3 4 12))
        ("Drawing3" (1998 5 4 3 4 12))
        ("Drawing4" (2001 5 4 3 4 13))
        ("Drawing5" (2001 5 4 3 4 12))
       )
    )
  )
  (princ)
)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12921
  • London, England
Re: Sort List retrieved from vla-file-systime
« Reply #2 on: July 17, 2009, 10:06:03 AM »
Nice one Alan,

I used that thought process, but your program is much easier to read  :-)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Sort List retrieved from vla-file-systime
« Reply #3 on: July 17, 2009, 10:25:51 AM »
PS it's vl-file-systime and not vla-file-systime :evil:
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Sort List retrieved from vla-file-systime
« Reply #4 on: July 17, 2009, 10:42:56 AM »
Code: [Select]
(defun SortBySysTime ( filelist )
    (vl-sort filelist
       '(lambda (a b)
            (<
                (apply '+ (mapcar '* (cadr a) '(1e10 1e8 0 1e6 1e4 1e2 1)))   
                (apply '+ (mapcar '* (cadr b) '(1e10 1e8 0 1e6 1e4 1e2 1)))   
            )
        )
    )
)

Code: [Select]
(defun c:TestSort ()
    (mapcar 'print
        (SortBySysTime
           '(
                ("Drawing1" (2001 4 3 8 10 6 52))
                ("Drawing2" (1999 5 2 4 3 4 12))
                ("Drawing3" (1998 5 3 4 3 4 12))
                ("Drawing4" (2001 5 1 4 3 4 13))
                ("Drawing5" (2001 5 7 4 3 4 12))
            )
        )
    )
    (princ)
)

(c:TestSort)

("Drawing3" (1998 5 3 4 3 4 12))
("Drawing2" (1999 5 2 4 3 4 12))
("Drawing1" (2001 4 3 8 10 6 52))
("Drawing5" (2001 5 7 4 3 4 12))
("Drawing4" (2001 5 1 4 3 4 13))

Edit: Works with unmodified data, that is, no need to remove the week number. If you do intend to remove the week number before passing to the SortBySysTime function remove the zero (0) from the '(1e10 1e8 0 1e6 1e4 1e2 1) list in the SortBySysTime  function.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Lee Mac

  • Seagull
  • Posts: 12921
  • London, England
Re: Sort List retrieved from vla-file-systime
« Reply #5 on: July 17, 2009, 10:45:25 AM »
PS it's vl-file-systime and not vla-file-systime :evil:

Oops!  :oops:

Lee Mac

  • Seagull
  • Posts: 12921
  • London, England
Re: Sort List retrieved from vl-file-systime
« Reply #6 on: July 17, 2009, 10:48:18 AM »
Michael, I also considered an addition method, but I couldn't see how I could get it to work as, obviously a drawing created earlier in the year but later in the month will cause errors...

But I see that you have countered that by using the multipliers...  Where do you get your ideas from!  :lol:

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Sort List retrieved from vl-file-systime
« Reply #7 on: July 17, 2009, 10:49:52 AM »
Just a caveat -- I seem to recall that the vl-file-systime is a little flakey, insomuch as it may not report the systime for drawings currently open by AutoCAD (if memory serves me). The upshot being you may have to pre-process the file list before passing it to a function like SortBySysTime -- lest it take a rake in the face.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Sort List retrieved from vl-file-systime
« Reply #8 on: July 17, 2009, 10:51:56 AM »
Where do you get your ideas from! :lol:

I dunno, I used to smoke pot and partake of hallucinogens in my teens, early twenties. :shrug:
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Sort List retrieved from vl-file-systime
« Reply #9 on: July 17, 2009, 11:34:21 AM »
Another attempt.  8-) 

Code: [Select]
;;  CAB 07/17/09
;;  sort list given the position order to sort on
;;  positions may be ignored by omitting them from the order list
(defun sort_systime (order lst / iidx)
  (setq len (length order))
  (vl-sort lst
           '(lambda (e1 e2 / idx)
              (setq idx -1)
              (while
                (and
                  (< (setq idx (1+ idx)) len)
                  (setq iidx (nth idx order))
                  (= (nth iidx (cadr e1)) (nth iidx (cadr e2)))
                )
              )
              (< (nth iidx (cadr e1)) (nth iidx (cadr e2)))
            )
  )
)


Code: [Select]
(defun c:test ()
  (mapcar
    'print
    (sort_systime
      '(0 1 3 4 5) ; ignore position 2
      '(("Drawing1" (2001 4 8 10 6 52))
        ("Drawing2" (1999 5 4 3 4 12))
        ("Drawing3" (1998 5 4 3 4 12))
        ("Drawing4" (2001 5 7 3 4 13))
        ("Drawing5" (2001 5 1 3 4 12))
       )
    )
  )
  (princ)
)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Sort List retrieved from vl-file-systime
« Reply #10 on: July 17, 2009, 11:58:02 AM »
Attempting a more general sort function.
"Sort on index of list" which returns the sort index


Code: [Select]
;;  return a sort index based on the sort order given for the list
;;  data types must match else error
(defun sort_list (order lst / iidx)
  (setq len (length order))
  (vl-sort-i lst
           '(lambda (e1 e2 / idx)
              (setq idx -1)
              (while
                (and
                  (< (setq idx (1+ idx)) len)
                  (setq iidx (nth idx order))
                  (= (nth iidx e1) (nth iidx e2))
                )
              )
              (< (nth iidx e1) (nth iidx e2))
            ))
)

Code: [Select]
(defun c:test (/ lst)
  (setq lst  ; just for test example
         '(("Drawing1" (2001 5 8 "D" 4 10))
           ("Drawing2" (1999 5 4 "a" 4 12))
           ("Drawing3" (1998 5 4 "a" 4 12))
           ("Drawing4" (2001 5 7 "C" 4 13))
           ("Drawing5" (2001 5 1 "B" 4 12))
           ("Drawing6" (2001 5 1 "A" 4 12))
          ))
  (mapcar
    'print
    (setq newlst
           (mapcar '(lambda (x) (nth x lst)) ; create the sorted list
                   (sort_list ; based on nth order
                     '(0 1 4 3 5) ; ignore position 2 & swap positions 3 & 4
                     (mapcar 'cadr lst) ; send only the sublist
                   ))))
  (princ)
)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Sort List retrieved from vl-file-systime
« Reply #11 on: July 17, 2009, 12:20:49 PM »
Generic sort (non nested) list function:

Code: [Select]
(defun SortList ( lst / foo )

    (defun foo ( a b / i j )
        (cond
            ((or (null (setq i (car a))) (null (setq j (car b)))) nil)
            ((< i j))
            ((< j i) nil)
            ((foo (cdr a) (cdr b)))
        )
    )

    (vl-sort lst 'foo)
   
)

Code: [Select]
(progn
    (mapcar 'print
        (SortList
           '(
                (2001 4 8 10 6 52)
                (2001 4 8 10 6 52) ;; test duplicate list
                (1999 5 4 3 4 12)
                (1998 5 4 3 4 12)
                (2001 5 4 3 4 13)
                (2001 5 4 3 4 12)
            )
        )
    )
    (princ)
)

(1998 5 4 3 4 12)
(1999 5 4 3 4 12)
(2001 4 8 10 6 52)
(2001 4 8 10 6 52)
(2001 5 4 3 4 12)
(2001 5 4 3 4 13)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Sort List retrieved from vl-file-systime
« Reply #12 on: July 17, 2009, 12:32:26 PM »
How about an index so the user can sort the lists in an 'out of order sequence' for the elements.
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12921
  • London, England
Re: Sort List retrieved from vl-file-systime
« Reply #13 on: July 17, 2009, 12:38:39 PM »
Woww guys, I never expected this much  8-)

Just a quick question Michael, regarding your "generic sort" function.

I am not too sure about how vl-sort works - is it such that if the predicate function returns T, then the items are swapped in the list? Or am I waaaayy off track?

Lee

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Sort List retrieved from vl-file-systime
« Reply #14 on: July 17, 2009, 12:43:34 PM »
There's no swapping. The foo predicate function returns T if the first item in list a (i) is less than the first item in list b (j). If i is greater than j then false. If they are equal then it evaluates the second item, the third item ... ad infinitum, returning false in the event that one or more lists has no remaining items.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst