Jump to content

Ascending order of strings - Query


aaryan

Recommended Posts

Hi All,

 

I am trying to sort multiple strings in an ascending order. However the results are not as expected because of the format. Please have a look.

 

(SETQ A "XXX, 3\", (STD) X  1'-0 1/4\" PIECE")
(SETQ B "XXX, 3\", (STD) X  8\" PIECE")

 

(< A B) ; gives me T whereas it should be nil 
       ; because A is of 1 foot and B is only 8 inch piece

 

Please note there could be multiple instances in one string.

 

My approach is to convert each pattern into the decimal (but how? I am confused here).

 

Any help would be appreciated.

 

Thanks

Link to comment
Share on other sites

Thanks for your reply Tharwat but this is not what I was looking for.

 

The strings are the description of the piping components which contains the length in architectural units. I want to sort them in ascending order according to length mentioned somewhere between in the description.

 

A new examples are:

 

(setq a "(STD) X  1'-0 1/4\" - TEST")
(setq b "(STD) X  8\" - TEST")

 

Hope my question is clear.

 

Thanks

Link to comment
Share on other sites

Perhaps:

(vl-sort '("(STD) X  1'-0 1/4\" - TEST"	    "(STD) X  8\" - TEST"
   "(STD) X  6\" - TEST"	    "(STD) X  9\" - TEST"
   "(STD) X  3\" - TEST"
  )
 '>
)
;;;("(STD) X  9\" - TEST"
;;;  "(STD) X  8\" - TEST"
;;;  "(STD) X  6\" - TEST"
;;;  "(STD) X  3\" - TEST"
;;;  "(STD) X  1'-0 1/4\" - TEST"
;;
;;;_$

Edited by ronjonp
Link to comment
Share on other sites

Nice one ronjonp but I can see problems maybe that if the descriptions dont have patterns will not sort correct. It may need some form of converting the lengths to real numbers then sort this would remove the description dependency.

Link to comment
Share on other sites

; (KGA_String_ParseNumbers "12'3/4\" ABC 5.6D.7.8 -9-10.0")      => (144.75 5.6 0.7 0.8 -9 -10.0)
; (KGA_String_ParseNumbers "XXX, 1\", (STD) X 1'-0 1/4\" PIECE") => (1.0 12.25)
(defun KGA_String_ParseNumbers (str / N_Str_To_Num ret sub)
 (defun N_Str_To_Num (str)
   ((if (not (wcmatch str "*[~-0-9]*,-,?*-*")) atoi distof) str)
 )
 (setq str (vl-string->list str))
 (repeat (1+ (length str)) ; 1+ to ensure processing of final sub.
   (cond
     ((<= 48 (car str) 57) ; 0-9.
       (setq sub (cons (car str) sub))
     )
     ((vl-position (car str) '(32 34 39 47)) ; (vl-string->list " \"'/")
       (if
         (or
           (vl-position (car str) sub)
           (not (<= 48 (car sub) 57)) ; Previous item added to sub must be a number.
           (and (= (car str) 32) (not (vl-position 39 sub)))
         )
         (if sub
           (progn
             (setq ret (cons (N_Str_To_Num (vl-list->string (reverse sub))) ret))
             (setq sub nil)
           )
         )
         (setq sub (cons (car str) sub))
       )
     )
     ((= (car str) 45) ; (ascii "-")
       (if (= (car sub) 39) ; (ascii "'")
         (setq sub (cons (car str) sub))
         (progn
           (if sub ; "-" has to be added to sub first if the number is decimal.
             (setq ret (cons (N_Str_To_Num (vl-list->string (reverse sub))) ret))
           )
           (setq sub (list (car str)))
         )
       )
     )
     ((= (car str) 46) ; (ascii ".")
       (if
         (or
           (vl-position (car str) sub)
           (= (car sub) 47) ; "." should not come after "/".
         )
         (progn
           (if sub
             (setq ret (cons (N_Str_To_Num (vl-list->string (reverse sub))) ret))
           )
           (setq sub (list (car str)))
         )
         (setq sub (cons (car str) sub))
       )
     )
     (sub
       (setq ret (cons (N_Str_To_Num (vl-list->string (reverse sub))) ret))
       (setq sub nil)
     )
   )
   (setq str (cdr str))
 )
 (vl-remove nil (reverse ret))
)

; (setq lst
;   '(
;     "XXX, 3\", (STD) X  6\" PIECE"
;     "XXX, 1\", (STD) X  6\" PIECE"
;     "XXX, 3\", (STD) X  1'-0 1/4\" PIECE"
;     "XXX, 1\", (STD) X  1'-0 1/4\" PIECE"
;     "XXX, 3\", (STD) X  8\" PIECE"
;     "XXX, 1\", (STD) X  8\" PIECE"
;   )
; )

; (SortTest lst) =>
; (
;   "XXX, 1\", (STD) X  6\" PIECE"
;   "XXX, 1\", (STD) X  8\" PIECE"
;   "XXX, 1\", (STD) X  1'-0 1/4\" PIECE"
;   "XXX, 3\", (STD) X  6\" PIECE"
;   "XXX, 3\", (STD) X  8\" PIECE"
;   "XXX, 3\", (STD) X  1'-0 1/4\" PIECE"
; )
(defun SortTest (lst)
 (mapcar
   'cadr
   (vl-sort
     (mapcar
       '(lambda (str) (list (KGA_String_ParseNumbers str) str))
       lst
     )
     '(lambda (a b / ret)
       (vl-some
         '(lambda (c d)
           (cond
             ((< c d) (setq ret T) T)
             ((> c d) (setq ret nil) T)
           )
         )
         (car a)
         (car b)
       )
       ret
     )
   )
 )
)

Edited by Roy_043
Improved parser funtion
Link to comment
Share on other sites

@Roy,

 

Shouldn't the result have the 8" and 6" swapped like so?

; (SortTest lst) =>

; ( "XXX, 1\", (STD) X 8\" PIECE"

; "XXX, 1\", (STD) X 6\" PIECE"

; "XXX, 1\", (STD) X 1'-0 1/4\" PIECE"

; "XXX, 3\", (STD) X 8\" PIECE"

; "XXX, 3\", (STD) X 6\" PIECE"

; "XXX, 3\", (STD) X 1'-0 1/4\" PIECE"

; )

Link to comment
Share on other sites

@ronjonp:

No: 6"

BTW:

The parser function doesn't handle 1'-0 1/4" properly as it assumes that the minus sign can only occur at the start of a numerical string.

 

Edit: Fixed the parser function in the code above. It can now handle 1'-0 1/4".

Edited by Roy_043
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...