aaryan Posted January 22, 2018 Share Posted January 22, 2018 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 Quote Link to comment Share on other sites More sharing options...
Tharwat Posted January 22, 2018 Share Posted January 22, 2018 Hi, Your list of strings is not clear to read but try this function acad_strlsort and it may what you are after. Quote Link to comment Share on other sites More sharing options...
aaryan Posted January 22, 2018 Author Share Posted January 22, 2018 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 Quote Link to comment Share on other sites More sharing options...
Roy_043 Posted January 22, 2018 Share Posted January 22, 2018 This may be useful. Quote Link to comment Share on other sites More sharing options...
aaryan Posted January 22, 2018 Author Share Posted January 22, 2018 Thanks Roy. I will have a look and let you know if any query. Thanks Quote Link to comment Share on other sites More sharing options...
ronjonp Posted January 22, 2018 Share Posted January 22, 2018 (edited) 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 January 22, 2018 by ronjonp Quote Link to comment Share on other sites More sharing options...
BIGAL Posted January 23, 2018 Share Posted January 23, 2018 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. Quote Link to comment Share on other sites More sharing options...
aaryan Posted January 23, 2018 Author Share Posted January 23, 2018 Thanks ronjonp. I am using the same method but as Bigal said it really needs the conversion to get the expected results. Quote Link to comment Share on other sites More sharing options...
aaryan Posted January 23, 2018 Author Share Posted January 23, 2018 This may be useful. Hello Roy I tried to use the code but unable to incorporate so. can you please guide how can this be done? Quote Link to comment Share on other sites More sharing options...
Roy_043 Posted January 23, 2018 Share Posted January 23, 2018 (edited) ; (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 January 23, 2018 by Roy_043 Improved parser funtion Quote Link to comment Share on other sites More sharing options...
ronjonp Posted January 23, 2018 Share Posted January 23, 2018 @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" ; ) Quote Link to comment Share on other sites More sharing options...
Roy_043 Posted January 23, 2018 Share Posted January 23, 2018 (edited) @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 January 23, 2018 by Roy_043 Quote Link to comment Share on other sites More sharing options...
ronjonp Posted January 23, 2018 Share Posted January 23, 2018 Gotcha .. got my ascending and descending bassackwards Quote Link to comment Share on other sites More sharing options...
aaryan Posted January 24, 2018 Author Share Posted January 24, 2018 Thanks roy! Appreciated. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.