Author Topic: vl-sort working in ACAD but not in BricCAD  (Read 4313 times)

0 Members and 1 Guest are viewing this topic.

mailmaverick

  • Bull Frog
  • Posts: 495
vl-sort working in ACAD but not in BricCAD
« on: September 15, 2023, 12:27:33 AM »
There seems to be some problem in functionality of vl-sort in BricsCAD, when using with SortStringWithNumberAsNumber.

Following code works in AutoCAD but not in BricsCAD :-

Code: [Select]
(defun c:test()
  (setq blklist (list (list "A20" "B2") (list "A13" "B1") (list "A9" "B1") (list "A16" "B4")))
                     
  (setq blklist (vl-sort blklist
                         '(lambda (e1 e2) (= (car (SortStringWithNumberAsNumber (list (car e1) (car e2)) T)) (car e1)))
                )
  )
  (princ)
)
(defun SortStringWithNumberAsNumber (ListOfString IgnoreCase / NorStrs count NormalizeNumberInString getcount)
;;;Function Normalize (add 0 befor number) number in string
;;; Count normalize symbols set in variable count
;;; CAB added count as an argument
  (defun NormalizeNumberInString (str count / ch i pat ret buf)
    (setq i 0
          pat '( "0" "1" "2" "3" "4" "5" "6" "7" "8" "9")
          ret ""
    ) ;_ end of setq
    (while (/= (setq ch (substr str (setq i (1+ i)) 1)) "")
      (if (vl-position ch pat)
        (progn ;_ end of setq
          (setq buf ch)
          (while (vl-position (setq ch (substr str (setq i (1+ i)) 1)) pat) (setq buf (strcat buf ch))) ;_ end of while
          (while (< (strlen buf) count) (setq buf (strcat "0" buf)))
          (setq ret (strcat ret buf))
        ) ;_ end of progn
      ) ;_ end of if
      (setq ret (strcat ret ch))
    ) ;_ end of while
    ret
  ) ;_ end of defun
  ;;-------------------------------------------------
  ;;  function to Count the longest number in string
  ;;  CAB added to get the correct COUNT
  (defun getcount (lst / count pat)
    (setq count 0)
    (setq pat '( "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"))
    (mapcar '(lambda (str / i maxlen ch)
                     (setq i 0
                           maxlen 0
                     )
                     (while (/= (setq ch (substr str (setq i (1+ i)) 1)) "")
                       (if (vl-position ch pat)       ; number
                         (setq maxlen (1+ maxlen))
                         (setq count (max count maxlen)
                               maxlen 0
                         )
                       )
                     )
                     (setq count (max count maxlen))  ;_<<< ADD 21.06.2007 by VVA
             )
            Lst
    )
    count
  )
  ;;===============================================
  (setq count (GetCount ListOfString)
        NorStrs (mapcar '(lambda (x) (NormalizeNumberInString x count)) ListOfString)
  )
  (and IgnoreCase (setq NorStrs (mapcar 'strcase NorStrs)))
  (mapcar '(lambda (x) (nth x ListOfString)) (vl-sort-i NorStrs '<))
)

Above code works fine in AutoCAD but gives following error in BricsCAD :-
Code: [Select]
; ----- Error around expression -----
; (CAR E1)
;
; error : Unknown Error in Lisp or CAD system or 'Stack Overflow'

ribarm

  • Gator
  • Posts: 3304
  • Marko Ribar, architect
Re: vl-sort working in ACAD but not in BricCAD
« Reply #1 on: September 17, 2023, 12:49:31 PM »
What should be return of (c:test)... I've checked in AutoCAD and it throwed nothing...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ribarm

  • Gator
  • Posts: 3304
  • Marko Ribar, architect
Re: vl-sort working in ACAD but not in BricCAD
« Reply #2 on: September 17, 2023, 12:57:39 PM »
What should be return of (c:test)... I've checked in AutoCAD and it throwed nothing...

Instead of putting (princ) at the end, I'd repeat return after sorting :

Quote
(defun c:Bricstest nil
  (setq blklist (list (list "A20" "B2") (list "A13" "B1") (list "A9" "B1") (list "A16" "B4")))
                     
  (setq blklist (vl-sort blklist
                         '(lambda (e1 e2) (= (car (SortStringWithNumberAsNumber (list (car e1) (car e2)) T)) (car e1)))
                )
  )
  blklist
)
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ribarm

  • Gator
  • Posts: 3304
  • Marko Ribar, architect
Re: vl-sort working in ACAD but not in BricCAD
« Reply #3 on: September 17, 2023, 01:03:49 PM »
But since the first letter in 'cars is the same and rest is numerical expressions, this hughe sorting routine could be shortened to just :

Code: [Select]
(defun c:Bricstest nil
  (setq blklist (list (list "A20" "B2") (list "A13" "B1") (list "A9" "B1") (list "A16" "B4")))
  (setq blklist (vl-sort blklist
                         '(lambda ( e1 e2 ) (if (= (car e1) (car e2)) (< (cadr e1) (cadr e2)) (< (car e1) (car e2)))
                )
  )
)
« Last Edit: September 17, 2023, 01:12:47 PM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

BIGAL

  • Swamp Rat
  • Posts: 1429
  • 40 + years of using Autocad
Re: vl-sort working in ACAD but not in BricCAD
« Reply #4 on: September 17, 2023, 09:12:25 PM »
I tried the code and got (("A13" "B1") ("A16" "B4") ("A20" "B2") ("A9" "B1")) I expected the ("A9" "B1") to be the 1st in the result.

I took a different approach, I split the list even further apart.

Code: [Select]
(setq blklist (list (list "A" 20 "B" 2) (list "A" 13 "B" 1) (list "A" 9 "B" 1) (list "A" 16 "B" 4)))
; sorts on 1st two items
(vl-sort blklist
'(lambda (a b)
    (cond
      ((< (car a) (car b)))
      ((= (car a) (car b)) (< (cadr a) (cadr b)))
    )
  )
)
(("A" 9 "B" 1) ("A" 13 "B" 1) ("A" 16 "B" 4) ("A" 20 "B" 2))


Adding more
Code: [Select]
(setq blklist (list (list "A" 20 "B" 2) (list "A" 13 "B" 1) (list "A" 9 "B" 1) (list "A" 16 "B" 4) (list "A" 9 "B" 3)))
(("A" 9 "B" 1) ("A" 9 "B" 3) ("A" 13 "B" 1) ("A" 16 "B" 4) ("A" 20 "B" 2))
Can then join back together, not tested very hard.


A man who never made a mistake never made anything

mailmaverick

  • Bull Frog
  • Posts: 495
Re: vl-sort working in ACAD but not in BricCAD
« Reply #5 on: September 24, 2023, 01:24:00 AM »
But why doesn't BricsCAD work with SortStringWithNumberAsNumber inside vl-sort, whereas AutoCAD works fine.

hmspe

  • Bull Frog
  • Posts: 362
Re: vl-sort working in ACAD but not in BricCAD
« Reply #6 on: September 24, 2023, 04:07:28 PM »
Most likely because your test conditions make no sense.  Sorts are generally largest to smallest or smallest to largest.  You are trying to sort equal to not equal with vl-sort.  You are also first sorting the first elements of a pair of lists using SSWNAN, then comparing the first element of the result against the first element of the first pair. 

What exactly are you trying to do?  You were asked for the expected output but you did not respond.

If you are trying to sort blklist by the first elements but with the numbers normalized i would do something like this:

Code - Auto/Visual Lisp: [Select]
  1. (defun c:test( / blklist)
  2.  
  3.   (defun SortAI (lst); = Sort Alphabetically, and within that by Integer value [of first element]  by Kent Cooper, AIA
  4.     (vl-sort
  5.       (vl-sort lst '(lambda (a b) (< (atoi (substr (car a) 2)) (atoi (substr (car b) 2)))))
  6.       '(lambda (c d) (< (substr (car c) 1 1) (substr (car d) 1 1)))
  7.     )
  8.   )
  9.  
  10.  
  11.   (setq blklist (list (list "A20" "B2") (list "A13" "B1") (list "A9" "B1") (list "A16" "B4")))
  12.   (sortAI blklist)
  13. )
  14.  
"Science is the belief in the ignorance of experts." - Richard Feynman

mailmaverick

  • Bull Frog
  • Posts: 495
Re: vl-sort working in ACAD but not in BricCAD
« Reply #7 on: September 30, 2023, 07:35:23 AM »
I am trying to sort List by comparing first element.
However, the first element need not be a single alphabet followed by a number. It can be anything. It may have multiple text and numeric values. For eg it can be something like :-
 (setq blklist (list (list "20HJHJE" "B2") (list "KJJAKJK" "B1") (list "NMNJH23" "B1") (list "823KKKH" "B4")))

The solution to my problem can only be attained if vl-sort works with "SortStringWithNumberAsNumber" otherwise not.

ribarm

  • Gator
  • Posts: 3304
  • Marko Ribar, architect
Re: vl-sort working in ACAD but not in BricCAD
« Reply #8 on: September 30, 2023, 12:20:04 PM »
Where do you see number in (car) of : (list "KJJAKJK" "B1") ???
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

mailmaverick

  • Bull Frog
  • Posts: 495
Re: vl-sort working in ACAD but not in BricCAD
« Reply #9 on: October 01, 2023, 07:10:42 AM »
Thats what I said. The list may or may not have number in first element. Thats why I want to use "SortStringWithNumberAsNumber" which encompasses all possibilities.

hmspe

  • Bull Frog
  • Posts: 362
Re: vl-sort working in ACAD but not in BricCAD
« Reply #10 on: October 01, 2023, 03:36:04 PM »
Perhaps try something like this:
Code - Auto/Visual Lisp: [Select]
  1. (defun sort_by_first (data ignore / data2 result)
  2.   (setq data2 list)
  3.   (foreach memb data
  4.     (setq data2 (cons (car memb) data2))
  5.   )
  6.   (setq data2 (SortStringWithNumberAsNumber2 data2 ignore))
  7.   (setq result (list))
  8.   (foreach memb2 data2
  9.     (foreach memb data
  10.       (if (= memb2 (car memb))
  11.         (setq result (cons memb result))
  12.       )
  13.     )
  14.   )
  15.   (reverse result)
  16. )
  17.  
  18.  
  19. (defun c:test1 ( / blklst)
  20.   (setq blklst (list (list "20HJHJE" "B2") (list "KJJAKJK" "B1") (list "NMNJH23" "B1") (list "823KKKH" "B4")))
  21.   (setq blklst (sort_by_first blklst T))
  22.   (print blklst)
  23.   (princ)
  24. )
  25.  

I used SortStringWithNumberAsNumber2 because I think it is a bit better.  It is included in the attached file.

You don't need to have SortStringWithNumberAsNumber inside another vl-sort function.  There is probably a way to modify SortStringWithNumberAsNumber to sort lists based on the first element.  For me it is easier keep it simple.

From what I can see your comparison function    (= (car (SortStringWithNumberAsNumber (list (car e1) (car e2)) T)) (car e1))    is invalid.  Sorting requires a inequality to have an ordered list.  I don't see how this comparison could work in Autocad or Bricscad. 
"Science is the belief in the ignorance of experts." - Richard Feynman

ribarm

  • Gator
  • Posts: 3304
  • Marko Ribar, architect
Re: vl-sort working in ACAD but not in BricCAD
« Reply #11 on: October 01, 2023, 06:50:46 PM »
@hmspe

I've looked at your attachment and I see 2 unneccesary lines :
(setq data2 list)
and
(setq result list)

Both of those things throws an error - soemthing like : bad function list <welmwlwe133> - blah blah blah...

Here is my revision of your proposal and I hope you don't mind posting it in code tags :

Code - Auto/Visual Lisp: [Select]
  1. (defun SortStringWithNumberAsNumber2 (sLst IgnoreCase /)                        ; by IRNEB at theswamp.org, thread "Windows Filename Sort"
  2.   (mapcar
  3.     (function
  4.       (lambda (idx)
  5.         (nth idx sLst)
  6.       )
  7.     )
  8.     (vl-sort-i
  9.       (mapcar
  10.         (function
  11.           (lambda (str / lst tmp)
  12.             (setq str (vl-string->list (if IgnoreCase (strcase str) str)))
  13.             (while str
  14.               (while (and str (> 11 (- (car str) 47) 0))
  15.                 (setq tmp (cons (car str) tmp)
  16.                       str (cdr str)
  17.                 )
  18.               )
  19.               (if tmp
  20.                 (setq lst (cons (atoi (vl-list->string (reverse tmp))) lst)
  21.                       tmp nil
  22.                 )
  23.               )
  24.               (while (and str (not (> 11 (- (car str) 47) 0)))
  25.                 (setq tmp (cons (car str) tmp)
  26.                       str (cdr str)
  27.                 )
  28.               )
  29.               (if tmp
  30.                 (setq lst (cons (vl-list->string (reverse tmp)) lst)
  31.                       tmp nil
  32.                 )
  33.               )
  34.             )
  35.             (reverse lst)
  36.           )
  37.         )
  38.         sLst
  39.       )
  40.       (function
  41.         (lambda (a b / lst p1 p2)
  42.           (setq lst (mapcar
  43.                       (function
  44.                         (lambda (x y)
  45.                           (if (= (type x) 'Str)
  46.                             (if (= (type y) 'Str)
  47.                               (if (< x y)
  48.                                 -1
  49.                                 (if (eq x y)
  50.                                   0
  51.                                   1
  52.                                 )
  53.                               )
  54.                               1
  55.                             )
  56.                             (if (= (type y) 'Str)
  57.                               -1
  58.                               (if (< x y)
  59.                                 -1
  60.                                 (if (= x y)
  61.                                   0
  62.                                   1
  63.                                 )
  64.                               )
  65.                             )
  66.                           )
  67.                         )
  68.                       )
  69.                       a b
  70.                     )
  71.           )
  72.           (and (setq p1 (vl-position -1 lst))
  73.                (or (not (setq p2 (vl-position 1 lst)))
  74.                    (< p1 p2)
  75.                )
  76.           )
  77.         )
  78.       )
  79.     )
  80.   )
  81. )
  82.  
  83. (defun sort_by_first (data ignore / data2 result)
  84.   (foreach memb data
  85.     (setq data2 (cons (car memb) data2))
  86.   )
  87.   (setq data2 (SortStringWithNumberAsNumber2 data2 ignore))
  88.   (foreach memb2 data2
  89.     (foreach memb data
  90.       (if (= memb2 (car memb))
  91.         (setq result (cons memb result))
  92.       )
  93.     )
  94.   )
  95.   (reverse result)
  96. )
  97.  
  98. (defun c:test1 ( / blklst)
  99.   (setq blklst (list (list "20HJHJE" "B2") (list "KJJAKJK" "B1") (list "NMNJH23" "B1") (list "823KKKH" "B4")))
  100.   (setq blklst (sort_by_first blklst T))
  101.   (print blklst)
  102.   (princ)
  103. )
  104.  

HTH.
M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

hmspe

  • Bull Frog
  • Posts: 362
Re: vl-sort working in ACAD but not in BricCAD
« Reply #12 on: October 01, 2023, 10:04:29 PM »
Marko,

Thanks.   (setq data2 list)  should have been   (setq data2 (list))

I prefer to manually initialize lists when I need to be sure they are empty before using CONS.  My experience long ago was that running a function a second time sometimes gave incorrect results if I did not.  It may not be needed but it should not hurt anything.   

I had no errors when I tested before posting.
"Science is the belief in the ignorance of experts." - Richard Feynman

ribarm

  • Gator
  • Posts: 3304
  • Marko Ribar, architect
Re: vl-sort working in ACAD but not in BricCAD
« Reply #13 on: October 02, 2023, 03:53:49 AM »
I just don't know what's wrong with this simple method :

Code - Auto/Visual Lisp: [Select]
  1. (defun c:test2 ( / carsblklst blklst )
  2.   (setq carsblklst (acad_strlsort (mapcar 'car (setq blklst (list (list "20HJHJE" "B2") (list "KJJAKJK" "B1") (list "NMNJH23" "B1") (list "823KKKH" "B4"))))))
  3.   (setq blklst (mapcar '(lambda ( x ) (assoc x blklst)) carsblklst))
  4. )
  5.  
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

hmspe

  • Bull Frog
  • Posts: 362
Re: vl-sort working in ACAD but not in BricCAD
« Reply #14 on: October 02, 2023, 05:37:06 PM »
I just don't know what's wrong with this simple method :

Whether ACAD_STRLSORT is appropriate depends on the expected result and on how well ordered the data is.     

 (acad_strlsort  '("P3" "P1" "P2" "P123" "P11"))
; ("P1" "P11" "P123" "P2" "P3")

If what you want is ASCII order it is fine.  For most of my purposes I would want the result to be P1, P2, P3, P11, P123
"Science is the belief in the ignorance of experts." - Richard Feynman