Page 1 of 2 12 LastLast
Results 1 to 10 of 17

Thread: Sorting a list of that contains a list of alphanumeric room numbers

  1. #1
    Member
    Join Date
    2013-07
    Posts
    20
    Login to Give a bone
    0

    Default Sorting a list of that contains a list of alphanumeric room numbers

    Hello All,

    I have been coding vanilla autolisp for many years I am totally stumped as to how to get the sorted output the way I need them to be. I do not profess to be an expert at programming, nor do I know all the clever tricks. With that said, I am in need the coding from one of the geniuses on the forum.

    I have used vl-sort and vl-sort-i and I am in need of sorting a list that contains a list of alphanumeric room numbers.

    The room numbering scheme is somewhat odd, but it is logical and each room number is unique, no repeats

    Generally, all room numbers are floor designation followed by a two digit room number.
    i.e. G01, G02, ... or 101, 102, 103 ...
    Additionally, if there is a sub-room then an alphabetic suffix is added G02A, 101A, 103A, 103B
    Sub-rooms can be 3 deep, 101BAA.

    vl-sort works perfectly if the room numbering scheme was this simple. The problem arises when a room is added at a later date that was needed to be between 102 and 103, and this is accomplished by using an alphabetic prefix A, B, ... A102 and so on.

    When vl-sort is done these room numbers that begin with a letter are sorted at the bottom of the list, when I want them to be in order mixed in with adjacent room numbers.


    Given a list similar to
    Code:
    (setq a-list 
        '(("101") ("102")
        ("A101") ("105") 
        ("104") ("104A") 
        ("104AB") ("104AA") 
        ("A104") ("A104A") 
        ("107") ("A105")) 
    )
    return-list needs to be
    Code:
       (("101") ("A101") 
        ("102") ("104") 
        ("104A") ("104AA") 
        ("104AB") ("A104") 
        ("A104A") ("105") 
        ("A105") ("107))
    To further complicate this sorting problem, some floor numbers begin with letters, G, i, R there is even an M2. With numbering G01, i01, R01 and M201 respectively.

    If possible, I would prefer a fully working function.

    My sincerest thanks in advance
    Steve
    Last edited by BlackBox; 2017-11-20 at 02:43 PM. Reason: Please use [CODE] Tags

  2. #2
    Member
    Join Date
    2013-07
    Posts
    20
    Login to Give a bone
    0

    Default Re: Sorting a list of that contains a list of alphanumeric room numbers

    I have even tried prefixing all room numbers that begin with a number and not a letter with the ascii character "ÿ" and performed an vl-sort-i and applied the indexed sort against the original list. This result is much closer to what I need, but still not quite right, yielding a result like:
    Code:
    '( ... ("104") ("A105") ("105") ("A105A") ("106") ("106A") ...)
    The ("105") should be either before ("A105") or after ("A105A"). Either would be OK, as long as the results are consistent. In my opinion, I think it would be best before ("A105")
    Last edited by BlackBox; 2017-11-20 at 05:05 PM. Reason: Please use [CODE] Tags

  3. #3
    Administrator BlackBox's Avatar
    Join Date
    2009-11
    Posts
    5,714
    Login to Give a bone
    0

    Default Re: Sorting a list of that contains a list of alphanumeric room numbers

    Welcome to AUGI.

    Give this a try:
    Code:
    (vl-load-com)
    
    (defun _RoomSort (a-list / _Add n data l rooms)
      ;; Example: (_RoomSort '(("104A") ("A104A") ("104AB") ("104AA") ("104") ("A104")))
      ;; Returns: (("104") ("104A") ("104AA") ("104AB") ("A104") ("A104A"))
      (defun _Add (prefix n suffix / room)
        (setq data
               (if (setq room (assoc n data))
                 (subst (cons n (cons (list prefix suffix) (cdr room))) room data)
                 (cons (cons n (cons (list prefix suffix) '())) data)
               )
        )
      )
      
      (foreach item a-list
        (setq n (car item))
        (cond
          ((wcmatch n "###") (_Add "*" n "*"))
          ((wcmatch n "@###") (_Add (substr n 1 1) (substr n 2) "*"))
          ((wcmatch n "@###@")
           (_Add (substr n 1 1) (substr n 2 3) (substr n 5))
          )
          ((or (wcmatch n "###@") (wcmatch n "###@@"))
           (_Add "*" (substr n 1 3) (substr n 4))
          )
        )
      )
    
      (foreach item (vl-sort data (function (lambda (a b) (> (car a) (car b)))))
        (setq n (car item))
        (foreach x (cdr item)
          (setq l (cons (list (strcat (car x) n (cadr x))) l))
        )
        (foreach room (reverse
                        (vl-sort
                          l
                          (function (lambda (a b) (< (car a) (car b))))
                        )
                      )
          (setq rooms (cons (list (vl-string-trim "*" (car room))) rooms))
        )
        (setq l nil)
      )
      rooms
    )

    Cheers
    "How we think determines what we do, and what we do determines what we get."

    Sincpac C3D ~ Autodesk Exchange Apps

    Computer Specs:
    Dell Precision 3660, Core i9-12900K 5.2GHz, 64GB DDR5 RAM, PCIe 4.0 M.2 SSD (RAID 0), 16GB NVIDIA RTX A4000

  4. #4
    Member
    Join Date
    2013-07
    Posts
    20
    Login to Give a bone
    0

    Default Re: Sorting a list of that contains a list of alphanumeric room numbers

    This is totally awesome. Obviously a tactic I had not thought of. As you probably well know, lists are rarely as simple as this, usually the sub-lists have several members and will vary in length, and the actual position of the room number might vary as well. Other information might include square footage, and /or building number, floor number, or whatever

    In the past I have tried to make these type of functions use nth instead of car (or variant). I have used code similar to this
    Code:
    	(setq   idx-List (vl-sort-i a-list (function (lambda (a b) (< (nth (1- pos) a) (nth (1- pos) b)))))
    		return-list (mapcar '(lambda (I) (nth I a-list)) idx-List)
    	)
    where pos represents the position where the function is to be applied, passed as a parameter into the function.

    would it be a huge inconvenience to have your function modified to have the position value passed to the function as well?
    Code:
    (_roomsort a-list pos)
    Thanks, if you are able to update it, I hope to thoroughly test it on several thousand room numbers for multiple buildings.

    Just so you know, how great value this will be, I manage over 650 floor plan drawings with a total in excess of 24,000 room numbers.
    Last edited by BlackBox; 2017-11-20 at 08:56 PM. Reason: Please use [CODE] Tags

  5. #5
    Administrator BlackBox's Avatar
    Join Date
    2009-11
    Posts
    5,714
    Login to Give a bone
    0

    Default Re: Sorting a list of that contains a list of alphanumeric room numbers

    Quote Originally Posted by stephen.hunter398967 View Post
    This is totally awesome. Obviously a tactic I had not thought of.
    No worries; we all start somewhere.

    Quote Originally Posted by stephen.hunter398967 View Post
    would it be a huge inconvenience to have your function modified to have the position value passed to the function as well?
    Hard to tell, without more information, and/or samples that demonstrate all potentialities (otherwise something gets missed, and could be a deal breaker later).

    You're welcome to take what you like from any code I post, and modify it as you need without attribution.


    Cheers
    "How we think determines what we do, and what we do determines what we get."

    Sincpac C3D ~ Autodesk Exchange Apps

    Computer Specs:
    Dell Precision 3660, Core i9-12900K 5.2GHz, 64GB DDR5 RAM, PCIe 4.0 M.2 SSD (RAID 0), 16GB NVIDIA RTX A4000

  6. #6
    Member
    Join Date
    2013-07
    Posts
    20
    Login to Give a bone
    0

    Default Re: Sorting a list of that contains a list of alphanumeric room numbers

    Does this help explain?

    This list example the room number is the second column
    Code:
    (setq a-list '((<Entity name: 4046dcb0> "177A" 194) 
      (<Entity name: 4046dd00> "177" 262)
      (<Entity name: 4046dd50> "175" 269)
      ... ) )
    This example the room number is in the fourth column
    Code:
    (setq a-list '(("UU" "062" "01" "100ELA" 21)
      ("UU" "062" "01" "100MSA" 25)
      ("UU" "062" "01" "100MSE" 26)
      ... ) )
    So, when passed the list to the (_roomsort a-list pos) and pos represents which column to sort
    Last edited by BlackBox; 2017-11-20 at 11:05 PM. Reason: Please use [CODE] Tags

  7. #7
    Member
    Join Date
    2013-07
    Posts
    20
    Login to Give a bone
    0

    Default Re: Sorting a list of that contains a list of alphanumeric room numbers

    I want to again thank you for your insight and coding, it was of great help. I studied your code last night and the idea I came up with that would work for me would be to modify your initial program by changing the following lines
    Code:
    (defun _RoomSort (a-list / _Add n data l rooms)
    to
    Code:
    (defun _RoomSort (a-list pos / _Add n data l rooms)
    and
    Code:
      (foreach item a-list
        (setq n (car item))
    to
    Code:
      (foreach item a-list
        (setq n (nth pos item))
    Then at the very end after the list rooms is sorted, then all that is needed to be done is step through the room list using foreach item in the sorted list rooms and substitute the full data info from the original a-list data

    Am I correct in this? Also, can you assist with the required coding for the substitution?

    Below is posted a the next version of code (less the list substitution needed at the end to the rooms list)
    Code:
    (setq lst3 '(("D" "3" "111" "104A" "junk5")
                 ("A" "5" "xxx" "A104A" "junk3")
                 ("B" "2" "ttt" "104AB" "junk2")
                 ("C" "5" "mmm" "104AA" "junk7")
                 ("E" "6" "rrr" "104" "junk8")
                 ("C" "5" "jjj" "108" "junk6")
                 ("C" "5" "ccc" "108AB" "junk4")
                )
    )
    (defun _RoomSort (a-list pos / _Add n data l rooms)
      ;; Example: (_RoomSort '(("104A") ("A104A") ("104AB") ("104AA") ("104") ("A104")))
      ;; Returns: (("104") ("104A") ("104AA") ("104AB") ("A104") ("A104A"))
      (defun _Add (prefix n suffix / room)
        (setq data
               (if (setq room (assoc n data))
                 (subst (cons n (cons (list prefix suffix) (cdr room))) room data)
                 (cons (cons n (cons (list prefix suffix) '())) data)
               )
        )
      )
      (foreach item a-list
        (setq n (nth pos item))
        (cond
          ((wcmatch n "###") (_Add "*" n "*"))
          ((wcmatch n "@###") (_Add (substr n 1 1) (substr n 2) "*"))
          ((wcmatch n "@###@")
           (_Add (substr n 1 1) (substr n 2 3) (substr n 5))
          )
          ((or (wcmatch n "###@") (wcmatch n "###@@"))
           (_Add "*" (substr n 1 3) (substr n 4))
          )
        )
      )
    
      (foreach item
               (vl-sort data (function (lambda (a b) (> (car a) (car b)))))
        (setq n (car item))
        (foreach x (cdr item)
          (setq l (cons (list (strcat (car x) n (cadr x))) l))
        )
        (foreach room (reverse
                        (vl-sort
                          l
                          (function (lambda (a b) (< (car a) (car b))))
                        )
                      )
          (setq rooms (cons (list (vl-string-trim "*" (car room))) rooms))
        )
        (setq l nil)
      )
      rooms
    )
    (_roomsort lst3 3)
    Last edited by BlackBox; 2017-11-21 at 02:44 PM. Reason: Please use [CODE] Tags, updated bottom code snippet formatting to fit view.

  8. #8
    Administrator BlackBox's Avatar
    Join Date
    2009-11
    Posts
    5,714
    Login to Give a bone
    0

    Default Re: Sorting a list of that contains a list of alphanumeric room numbers

    I had actually already started on this last night, but need to get a project submittal out this morning before I can revisit, as today's my last day before taking some vacation time (from work, not forums, etc.).

    The first thing that I did a bit differently, is that I placed the pos parameter before the a-list parameter in my '_RoomsSortByPos' sub-function, so that it mimics the nth LispFunction, given that's what it will now be based on.

    Cheers
    "How we think determines what we do, and what we do determines what we get."

    Sincpac C3D ~ Autodesk Exchange Apps

    Computer Specs:
    Dell Precision 3660, Core i9-12900K 5.2GHz, 64GB DDR5 RAM, PCIe 4.0 M.2 SSD (RAID 0), 16GB NVIDIA RTX A4000

  9. #9
    Member
    Join Date
    2013-07
    Posts
    20
    Login to Give a bone
    0

    Default Re: Sorting a list of that contains a list of alphanumeric room numbers

    The following (more or less) final coding seems to work wonderfully and the user has the option to specify which column has the room number to sort by.

    I added the ability to control the return list to be reversed or not.

    Lastly, I added the ability to handle a dotted pair list. Probably not the best way, but it does work.

    If anyone has improvements or comments, please feel free to comment.

    Code:
    (progn 
    
    ;; Examples:
    
    (setq lst2 '(("104A" . 10)
                    ("A104A" . 50)
                    ("104AB" . 65)
                    ("104AA" . 123)
                    ("104" . 203)
                    ("108" . 397)
                    ("108AB" . 99)
                   )
    )
    
    ;; Returns: (("104" . 203) ("104A" . 10) ("104AA" . 123) ("104AB" . 65) ("A104A" . 50) ("108" . 397) ("108AB" . 99))
    
    
    (setq lst3   '(("D" "3" "111" "104A" "junk5") 
                      ("A" "5" "xxx" "A104A" "junk3")
                      ("B" "2" "ttt" "104AB" "junk2")
                      ("C" "5" "ttt" "104AA" "junk2")
                      ("C" "5" "ttt" "104" "junk2")
                      ("C" "5" "ttt" "108" "junk2")
                      ("C" "5" "ttt" "108AB" "junk2")
                     )
    )
    
    ;; Returns:  (("C" "5" "ttt" "104" "junk2") ("D" "3" "111" "104A" "junk5") ("C" "5" "ttt" "104AA" "junk2") ("B" "2" "ttt" "104AB" "junk2") ("A" "5" "xxx" "A104A" "junk3") ("C" "5" "ttt" "108" "junk2") ("C" "5" "ttt" "108AB" "junk2"))
    ;;
    ;;
    ;; Note: Room numbers are assumed to be unique and no repeats
    ;;
    ;; pos - position of the room number in the sub-list, 0 indicates the first element of the sub-list
    ;; rev - if T, the the return list is reversed
    ;; a-list - The list that contains a sub-list of data that contains room numbers
    ;;
    (defun _RoomSort (pos rev a-list / n data l rooms dp 
    			_Add DottedPairP Dotted:Pair>Paired:List Paired:List>Dotted:Pair ;locally defined functions
    		)
    
    ;; =============  For main program see below  ==============
    
    ;; -------------  Locally defined functions   --------------
    
      (defun _Add (prefix n suffix / ) ;room)
        (setq data
               (if (setq room (assoc n data))
                 (subst (cons n (cons (list prefix suffix) (cdr room))) room data)
                 (cons (cons n (cons (list prefix suffix) '())) data)
               )
        )
      )
    
    ;; ------------
    
       ;; checks to see if the list is a list of dotted pairs
    
       (defun DottedPairP ( x ) (not (listp (cdar x))) )
    
    ;; -------------
    
      ;; Converts a list of dotted pairs to a list of paired lists
    
      (defun Dotted:Pair>Paired:List (x r / y)
         (foreach item x
    	(setq y (cons (list (car item) (cdr item)) y))
         )
         (if (not r) (reverse y) y)
      ) ;end defun
    
    ;; ------------
    
       ;; Converts a list of paired lists to a list of dotted pairs
    
       (defun Paired:List>Dotted:Pair (x r / y)
         (foreach item x
    	(setq y (cons (cons (car item) (cadr item)) y))
         )
         (if (not r) (reverse y) y)
      ) ;end defun
    
    
    ;; =============          Main Program          ===============
    
      (if (listp a-list)
       (progn 
        (if (DottedPairP A-List) ;checks to see if it's a list of dotted pairs, if so, then convert it
          (setq A-List (Dotted:Pair>Paired:List A-List nil) ;converts from list of dotted pairs to a list of paired lists
    	    dp T
          )
        )
        (foreach item a-list
          (setq n (nth pos item))
          (cond
            ((wcmatch n "###") (_Add "*" n "*"))
            ((wcmatch n "@###") (_Add (substr n 1 1) (substr n 2) "*"))
            ((wcmatch n "@###@")
             (_Add (substr n 1 1) (substr n 2 3) (substr n 5))
            )
            ((or (wcmatch n "###@") (wcmatch n "###@@"))
             (_Add "*" (substr n 1 3) (substr n 4))
            )
          )
        )
        (foreach item (vl-sort data (function (lambda (a b) (> (car a) (car b)))))
          (setq n (car item))
          (foreach x (cdr item)
            (setq l (cons (list (strcat (car x) n (cadr x))) l))
          )
          (foreach room 
    	(reverse (vl-sort l (function (lambda (a b) (< (car a) (car b))))) )
            (setq rooms (cons (list (vl-string-trim "*" (car room))) rooms))
          )
          (setq l nil)
        )
        (foreach item a-list	
    	(setq rooms (subst item (list (nth pos item)) rooms) )
        )
        (if dp 
          (setq rooms (Paired:List>Dotted:Pair rooms nil) )
        ) ;end if
    
        (if rev (reverse rooms) rooms)
       ) ;end progn
      ) ;end if
    
    ) ;end defun _RoomSort
    
    (princ (setq SortedRoomNumbers (_roomsort 0 T lst2)) )
    (princ "\n")
    (princ (setq SortedRoomNumbers (_roomsort 3 nil lst3)) )
    (princ)
    ) ;end progn
    Last edited by Opie; 2017-11-22 at 05:00 PM.

  10. #10
    Member
    Join Date
    2013-07
    Posts
    20
    Login to Give a bone
    0

    Default Re: Sorting a list of that contains a list of alphanumeric room numbers

    I hate to say this, but there seems to be a bug in your program,

    given a room list

    Code:
    (setq lst4 '(("100CRC") ("100ZOA") ("120") ("100MSV") ("100VSH") ("100MSQ") ("100MSR") 
    ("100MST") ("100MSM") ("100MSN") ("100MSL") ("100MSK") ("100VSG") ("100VSF") 
    ("100MSI") ("100MSH") ("100MSE") ("100ELB") ("100MSD") ("100ELA") ("100VSE") 
    ("100VSD") ("129") ("100CRB") ("A141") ("100MSA") ("100ESA") ("108") ("136") 
    ("174") ("100VSA") ("106") ("100VSC") ("116") ("100VSB") ("100CRA") ("100STA") 
    ("140") ("160") ("171") ("101") ("100STC") ("100STB") ("150") ("114") ("118") 
    ("134A") ("144") ("165") ("177A") ("177") ("175") ("167") ("163") ("161") 
    ("155") ("178") ("176") ("170") ("172") ("153") ("149") ("149A") ("147") 
    ("143") ("141") ("137") ("135") ("133") ("131") ("139") ("138B") ("138A") 
    ("138") ("134") ("130") ("132") ("126") ("130A") ("124") ("122") ("116A") 
    ("110") ("115") ("119") ("117") ("113") ("107") ("105") ("145") ("146") 
    ("100PLB"))
    )
    Returns:

    Code:
    (("101") ("105") ("106") ("107") ("108") ("110") ("113") ("114") ("115") 
    ("116") ("116A") ("117") ("118") ("119") ("120") ("122") ("124") ("126") 
    ("129") ("130") ("130A") ("131") ("132") ("133") ("134") ("134A") ("135") 
    ("136") ("137") ("138") ("138A") ("138B") ("139") ("140") ("141") ("A141") 
    ("143") ("144") ("145") ("146") ("147") ("149") ("149A") ("150") ("153") 
    ("155") ("160") ("161") ("163") ("165") ("167") ("170") ("171") ("172") ("174") 
    ("175") ("176") ("177") ("177A") ("178"))
    All the 100xxx room numbers were dropped.

    If I change the cond section to

    Code:
        (cond
    	((or (wcmatch n "###") (wcmatch n "@##"))	    (_Add "*" n "*")
    	)
    	((wcmatch n "@###") (_Add (substr n 1 1) (substr n 2) "*"))
    
    	((or (wcmatch n "@###@") (wcmatch n "@###@@") (wcmatch n "@###@@@") )
    	    (_Add (substr n 1 1) (substr n 2 3) (substr n 5))
    	)
    	((or (wcmatch n "###@") (wcmatch n "###@@") (wcmatch n "###@@@"))
    	    (_Add "*" (substr n 1 3) (substr n 4))
    	)
    	((or (wcmatch n "@@##@") (wcmatch n "@@##@@") (wcmatch n "@@##@@@"))
    	    (_Add (substr n 1 1) (substr n 2 3)  (substr n 5))
    	)
    	(_Add "*" n "*") ;needed to do this if all conditions above are not met, so room numbers do not get deleted from sorted list
        )
    seems to correct the problem.
    Last edited by frisbee; 2017-11-22 at 05:20 PM. Reason: [code] tags added ~Opie

Page 1 of 2 12 LastLast

Similar Threads

  1. List Sorting in Lisp
    By avinash00002002 in forum AutoLISP
    Replies: 7
    Last Post: 2014-09-14, 05:59 PM
  2. Sorting parameters list
    By dduarte in forum Revit Architecture - General
    Replies: 3
    Last Post: 2009-02-10, 04:50 PM
  3. sorting drawing list
    By ray salmon in forum Revit Architecture - General
    Replies: 2
    Last Post: 2009-01-24, 12:09 AM
  4. Sorting a drawing list
    By WolffG in forum Revit Architecture - General
    Replies: 4
    Last Post: 2005-11-07, 07:54 PM
  5. Sorting a drawing list
    By christo4robin in forum Revit Architecture - General
    Replies: 1
    Last Post: 2004-01-14, 06:58 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •