pBe Challenge : Wcmatch patterns

pBe Challenge : Wcmatch patterns

pbejse
Mentor Mentor
1,986 Views
28 Replies
Message 1 of 29

pBe Challenge : Wcmatch patterns

pbejse
Mentor
Mentor

Here's a list of filenames:

 

(setq lst '("1396_000-ERT-LAS-DWG-ST03-00-1001.dwg" "1396_000-ERT-LAS-DWG-ST03-00-1001_recover.dwg"
 	    "1396_000-ERT-IRR-DWG-ST03-00-5002.dwg" "1396_000-ERT-MEP-DWG-ST03-01-8001.dwg" 
 	    "1396_000-ERT-MEP-DWG-ST03-01-8112.dwg" "1396_000-ERT-MEP-DWG-ST03-01-8112_xx.dwg"
 	    "SCOPE OF WORK.dwg" "Third floor.dwg"))

 

Your challenge if you choose to accept it is to come up with the best pattern for filter to be used as argument for _FilterThisMrRobot sub

 

(Defun _FilterThisMrRobot (wt l)
  (vl-remove-if-not
    '(lambda (sg)
       (vl-some '(lambda (f)
		   (wcmatch sg f)) wt)
       )
    l
  )
)

 

Expected pattern would be

 

'("1396_000-ERT-@@@-DWG-ST03-0#-####.dwg")
(__FilterThisMrRobot '("1396_000-ERT-???-DWG-ST03-0#-####.dwg") LST)
Result:
"1396_000-ERT-LAS-DWG-ST03-00-1001.dwg" 
"1396_000-ERT-IRR-DWG-ST03-00-5002.dwg" 
"1396_000-ERT-MEP-DWG-ST03-01-8001.dwg" 
"1396_000-ERT-MEP-DWG-ST03-01-8112.dwg" 

 

Here's more samples [ Correction ]

(setq lst '("LEW-SD-YEE-SW-LA-LY-20092.dwg" "LEW-SD-YEE-SW-LA-LY-10092.dwg"
	    "XX_LEW-SD-YEE-SW-LA-LY-10092.dwg" "LEW-SD-YEE-SS-AR-LY-20102.dwg"
	    "LEW-SD-YEE-SS-AR-L1-50092.dwg" "LEW-SD-YEE-SS-AR-L1-50092_recover.dwg"
	    "LEW-SD-YEE-SS-AR-LY-01110.dwg" "From Ground Floor.dwg"
	    "LEW-SD-YEE-SS-AR-LY-01100_latest.dwg"))

Pattern(s): '("LEW-SD-YEE-@@-@@-L?-#####.dwg")
Pattern(s): '("LEW-SD-YEE-S@-@@-LY-#####.dwg") Results: "LEW-SD-YEE-SW-LA-LY-20092.dwg" "LEW-SD-YEE-SW-LA-LY-10092.dwg" "LEW-SD-YEE-SS-AR-LY-20102.dwg" "LEW-SD-YEE-SS-AR-L1-50092.dwg" <-- Should not been here as there's only one of these pattern "LEW-SD-YEE-SS-AR-LY-01110.dwg"

And to make it a bit more challenging, if  A pattern appears more than 3 times, then it should be included on the list

(setq lst '("300612-22-A-101.dwg" "300612-22-D-312.dwg" "300612-22-D-313.dwg" "300612-22-D-501.dwg"
	    "300612-22-D-313_updated.dwg" "300612-22-X-01.dwg" "300612-22-X-02.dwg""300612-22-X-10.dwg"
	    "300612-22-X-25.dwg" "D-TEMPLATE.dwg"	))
Pattern(s): '("300612-22-@-###.dwg" "300612-22-X-##.dwg")
Results:
"300612-22-0-101.dwg" <-- Should not been here as there's only one of these pattern
"300612-22-A-101.dwg" <---- changed 0 to A for completeness "300612-22-D-312.dwg" "300612-22-D-313.dwg" "300612-22-D-501.dwg" "300612-22-X-01.dwg" "300612-22-X-02.dwg" "300612-22-X-10.dwg" "300612-22-X-25.dwg"

Hope you guys like it and have a go at it

 

EDIT:  Revised the samples and result to comply with the requirements

Accepted solutions (3)
1,987 Views
28 Replies
Replies (28)
Message 2 of 29

Sea-Haven
Mentor
Mentor

Just guessing if use filter _&- so start with 

1396 No

then 1396_000 No

then 1396_000-ERT No

then 1396_000-ERT-??? yes 

So keep reducing the list of results maybe till get to required. Would have choice wildcard or actual. ??? v's LAS

 

Just not sure how would approach a reducing pyramid of actions.

0 Likes
Message 3 of 29

marko_ribar
Advisor
Advisor

I must admit, your challenge task is very well conceived and composed...

 

Not long ago, there was something similar asked at CadTutor site/forum by somewhat renown user Jonathan Handojo (author of few LISP applications posted at download section of CadTutor site : https://www.cadtutor.net/forum/files/ )

 

I answered to his request, by coding sub function that could be used for very similar purposes like you described in challenge... The difference between challenge and his request is that it was asked for helper/sub (non command) function that finds matching pattern between 2 proposed strings that are supposed to be filenames specifications...

His request was not so sophisticated like you described here - he only wanted very general solution involving only "*" character usage in pattern/result...

 

So, if you want, you can pull out patterns from matching all pairs in folder without repetition :

 

(defun processfolder ( filenameslist / unique resultpatterns )

  (defun unique ( list / a r )
    (while (setq a (car list))
      (if (vl-some '(lambda ( x ) (equal a x)) (cdr list))
        (setq r (cons a r) list (vl-remove-if '(lambda ( x ) (equal a x)) (cdr list)))
        (setq r (cons a r) list (cdr list))
      )
    )
    (reverse r)
  )

  (foreach filename1 filenameslist
    (setq filenameslist (cdr filenameslist))
    (foreach filename2 filenameslist
      (setq resultpatterns (cons (str1mchstr2 filename1 filename2) resultpatterns))
    )
  )
  (unique resultpatterns)
)

 

helper/sub (non command) function - (str1mchstr2) can be found here :

https://www.cadtutor.net/forum/topic/74031-matching-pattern-of-two-strings/?do=findComment&comment=5... 

 

Well, it may look like a simple answer to the challenge, but it may have some possible advantages exactly/just because of very essential/fundamental way/approach to solving this task...

 

HTH.

Regards, M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 4 of 29

pbejse
Mentor
Mentor

@marko_ribar wrote:

I must admit, your challenge task is very well conceived and composed...

...

Well, it may look like a simple answer to the challenge, but it may have some possible advantages exactly/just because of very essential/fundamental way/approach to solving this task...


Thank you @marko_ribar.  I'll have a look at your contribution and let you know.

 

0 Likes
Message 5 of 29

pbejse
Mentor
Mentor

@Sea-Haven wrote:

Just not sure how would approach a reducing pyramid of actions.


That's where the fun begins @Sea-Haven 😊

Let us know how you getting on with a solution.

 

Now i'll need to figure out how I will approach this myself 😀

 

0 Likes
Message 6 of 29

john.uhden
Mentor
Mentor

@pbejse 

You may have been challenged by ranges, but I am challenged by the purpose of this challenge.  I don't get it.  So how about just "*" ?

I mean that usually we have a definite pattern in mind, but you seem to be implying some kind of variable pattern, or something.  I just don't get it.

 

John F. Uhden

0 Likes
Message 7 of 29

john.uhden
Mentor
Mentor

@marko_ribar 

I must compliment you on your use of LIST for knowing it can be used as a variable because it was localized.

Yes, everyone, even input variables are considered as locals.

(defun test (pi)
  (princ (setq pi "apple"))
  (princ)
)
Command: (test 1) apple

Command: !pi 3.14159

John F. Uhden

0 Likes
Message 8 of 29

pbejse
Mentor
Mentor

@john.uhden wrote:

You may have been challenged by ranges, but I am challenged by the purpose of this challenge. 


JohnsPurpose.gif


@john.uhden wrote:

I don't get it.  So how about just "*" ?

I mean that usually we have a definite pattern in mind, but you seem to be implying some kind of variable pattern, or something.  I just don't get it.


That's the thing. we don't know what the pattern will be but only after you have a list.  That is what the challenge is all about. The list will be available for the sub only when you run the program, I should've have made that clear from the get go. And to make it more precise, try to avoid using "*" 

 

Oh you got it. I know you do 😄

 

0 Likes
Message 9 of 29

Sea-Haven
Mentor
Mentor

1st pass

Choose

LEW & From & XX so LEW chosen xx and from removed

2nd pass 

LEW-SD so skip as only 1 choice

3rd pass

LEW-SD-YEE so skip as only 1 choice

4th pass

LEW-SD-YEE-SW & LEW-SD-YEE-SS choose

and so on 

tricky bit is options like 1234 or ####

 

Will see how far I can get. I can use either my multi getvals or my multi radio buttons to choose.

0 Likes
Message 10 of 29

john.uhden
Mentor
Mentor

@pbejse 

So, the challenge is to find/build a pattern that matches most of the items without a simple "*" ?

But that could be just "???-????-???? etc."

There must be more stringent rules, no?

Gotta go... later...

John F. Uhden

0 Likes
Message 11 of 29

marko_ribar
Advisor
Advisor

Greetings...

I took some of my free hours to arrange posted sub functions that could be useful for this challenge task...

 

I was playing more with user friendly ways of aquiring desirable data input, than working on specific task - solving problem... Either way, if you want, you can use my LISP template to do testings with your own codes/functions...

 

I'd tried to cobble everything needed that is available for normal/usual usage of CAD software to make desired master routine useful for this specific task...

Used : Express Tools - acet-xxx functions , DCL - Dialog Control Language, just a little Visual Lisp functions (built-in), (Robert McNeel) DosLib addon functions, and almost everything else predominantly used by standard AutoLisp functions (built-in)...

 

;;; USED GENERAL NON COMMAND FUNCTIONS ;;;

;;; pattern matching between 2 strings ;;;
;;; https://www.cadtutor.net/forum/topic/74031-matching-pattern-of-two-strings/

(defun str1mchstr2 ( str1 str2 / unique* l1 l2 l2o a r q )

  (defun unique* ( l / a r )
    (while (setq a (car l))
      (if (and (= a 42) (vl-position 42 (cdr l)))
        (setq r (cons a r)
              l (member (vl-some (function (lambda ( x ) (if (/= x 42) x))) l) l)
        )
        (setq r (cons a r)
              l (cdr l)
        )
      )
    )
    (reverse r)
  )

  (setq l1 (vl-string->list str1))
  (setq l2 (vl-string->list str2))
  (setq l2o l2)
  (while (setq a (car l1))
    (setq l1 (cdr l1))
    (if (= a (car l2))
      (setq r  (cons a r)
            l2 (cdr l2)
      )
      (setq r  (cons 42 r)
            l2 (if (= (car l1) (car l2))
                 l2
                 (if (vl-position (car l1) l2)
                   (if (vl-position (car l1) r)
                     (progn
                       (setq q l2o)
                       (repeat (1+ (- (length r) (length (vl-remove (car l1) r))))
                         (setq q (cdr (member (car l1) q)))
                       )
                       (setq q (cons (car l1) q))
                     )
                     (cdr l2)
                   )
                   (cdr l2)
                 )
               )
      )
    )
  )
  (vl-list->string (unique* (reverse r)))
)

;;;
;;; (defun c:ttt1 nil (str1mchstr2 "Drawing_12_1297-2241079-LEVEL 50 - PRESSURE SERVICES - ZONE 3" "Drawing_6_1303-2241073-LEVEL 50 - PRESSURE SERVICES - ZONE 3"))
;;; (defun c:ttt2 nil (str1mchstr2 "Drawing_6_1303-2241073-LEVEL 50 - PRESSURE SERVICES - ZONE 3" "Drawing_12_1297-2241079-LEVEL 50 - PRESSURE SERVICES - ZONE 3"))
;;;
;;; "Drawing_*_1*-224107*-LEVEL 50 - PRESSURE SERVICES - ZONE 3" ;;; 


;;; process list with filenames-patterns by collecting each matching pattern (each string pair matching) and finally removing duplicates - used method : iteration ;;;
;;; filenameslist-patternslist - list with strings
;;; return - list with common matching pattern(s) string(s)

(defun process ( filenameslist-patternslist / unique resultpatterns )

  (defun unique ( l / a r )
    (while (setq a (car l))
      (if (vl-some (function (lambda ( x ) (equal a x))) (cdr l))
        (setq r (cons a r)
              l (vl-remove-if (function (lambda ( x ) (equal a x))) (cdr l))
        )
        (setq r (cons a r)
              l (cdr l)
        )
      )
    )
    (reverse r)
  )

  (foreach filename-pattern1 filenameslist-patternslist
    (setq filenameslist-patternslist (cdr filenameslist-patternslist))
    (foreach filename-pattern2 filenameslist-patternslist
      (setq resultpatterns (cons (str1mchstr2 filename-pattern1 filename-pattern2) resultpatterns))
    )
  )
  (unique resultpatterns)
)

;;; process list with filenames strings until matched pattern(s) become sinlge common matching pattern string - used method : recursion ;;;
;;; filenameslist-patternslist - list with strings representing filenames specifications
;;; return - common matching pattern string

(defun mainprocess ( filenameslist-patternslist )
  (if (> (length filenameslist-patternslist) 1)
    (mainprocess (process filenameslist-patternslist))
    (car filenameslist-patternslist)
  )
)

;;; collect list of filenames of all specific files residing in main/parent folder and all its sub/child folders ;;;
;;; libraryrootprefix - main/parent folder string
;;; filenamepattern - pattern describing specific non fungible characteristic to be used for processing/collecting filenames / nil ("*.*")
;;; return - list with filenames strings (full paths included) collected in specific folder tree that satisfy custom specific filter if it was provided and passed to evaluation

(defun _findfiles ( libraryrootprefix filenamepattern / subs processsubfolders folders fl r ) ;;; (_findfiles "F:\\ACAD ADDONS-NEW\\" "profile*.lsp")

  (defun subs ( folder )
    (vl-remove "." (vl-remove ".." (vl-directory-files folder nil -1)))
  )

  (defun processsubfolders ( rootfolder / subfolders )
    (setq subfolders (subs rootfolder))
    (foreach sub subfolders
      (if (= (substr rootfolder (strlen rootfolder)) "\\")
        (setq r (cons (strcat rootfolder sub) (processsubfolders (strcat rootfolder sub))))
        (setq r (cons (strcat rootfolder "\\" sub) (processsubfolders (strcat rootfolder "\\" sub))))
      )
    )
    r
  )

  (setq folders (append (list libraryrootprefix) (processsubfolders libraryrootprefix)))
  (foreach folder folders
    (foreach x (vl-directory-files folder filenamepattern 1)
      (setq fl (cons (strcat folder "\\" x) fl))
    )
  )
  (reverse fl)
)

;; Directory Files  -  Lee Mac
;; Retrieves all files of a specified filetype residing in a directory (and subdirectories)
;; dir - [str] Root directory for which to return filenames
;; typ - [str] Optional filetype filter (DOS pattern)
;; sub - [bol] If T, subdirectories of the root directory are included
;; Returns: [lst] List of files matching the filetype criteria, else nil if none are found

(defun LM:directoryfiles-main ( dir typ sub / LM:directoryfiles l ) ;;; why main function ? - purpose : clearing "l" variable (globals are not desirable in any case...)

  (defun LM:directoryfiles ( dir typ sub )
    (setq dir (vl-string-right-trim "\\" (vl-string-translate "/" "\\" dir)))
    (mapcar
      (function
        (lambda ( x )
          (setq l (append l (list (strcat dir "\\" x))))
        )
      ) (vl-directory-files dir typ 1)
    )
    (if sub
      (mapcar
        (function
          (lambda ( x )
            (if (not (wcmatch x "`.,`.`."))
              (LM:directoryfiles (strcat dir "\\" x) typ sub)
            )
          )
        )
        (vl-directory-files dir nil -1)
      )
    )
  )

  (LM:directoryfiles dir typ sub)
  l
)

;;; MAIN ROUTINE ;;;

;;;------------------------------------------------------------------------------------------------------------------------;;;
;;;                                                                                                                        ;;;
;;; FIND COMMON MATCHING PATTERN STRING OF ALL SPECIFIC FILES RESIDING IN MAIN/PARENT FOLDER AND ALL ITS SUB/CHILD FOLDERS ;;;
;;;                                                                                                                        ;;;
;;; By Marko Ribar, d.i.a. (architect) : 20.02.2022.                                                                       ;;;
;;;                                                                                                                        ;;;
;;;------------------------------------------------------------------------------------------------------------------------;;;

(defun c:folder_wcmatch_pattern ( / *error* LM:str->lst LM:editbox editbox_makedcl run_editbox_dcl tmp_dcl_filename dcl_id han filter folder fullfilenames filenames )

  (vl-load-com) ;;; load AciveX extensions (VLA-functions)...

  ;;; HELPER SUB FUNCTIONS...

  (defun *error* ( m )
    (vl-catch-all-apply 'term_dialog nil)
    (if m
      (prompt m)
    )
    (princ)
  )

  ;; String to List  -  Lee Mac
  ;; Separates a string using a given delimiter
  ;; str - [str] String to process
  ;; del - [str] Delimiter by which to separate the string
  ;; Returns: [lst] List of strings

  (defun LM:str->lst ( str del / len lst pos )
    (setq len (1+ (strlen del)))
    (while (setq pos (vl-string-search del str))
      (setq lst (cons (substr str 1 pos) lst)
            str (substr str (+ pos len))
      )
    )
    (reverse (cons str lst))
  )

  ;; Edit Box  -  Lee Mac
  ;; Displays a DCL Edit Box to obtain a string from the user
  ;; str - [str] Initial value to display ("" for none)
  ;; Returns: [str] Edit box contents if user pressed OK, else nil

  (defun LM:editbox ( str han )
    (if (new_dialog  "acad_txtedit" han)
      (progn
        (set_tile    "text_edit"    str)
        (action_tile "text_edit" "(setq str $value)")
        (if (zerop (start_dialog))
          (setq str nil)
        )
        (if (and han (< 0 han))
          (unload_dialog han)
        )
        str
      )
    )
  )

  (defun editbox_makedcl ( fullfilename / fn )
    (setq fn (open fullfilename "w"))
    (write-line "EditBox : dialog { key = \"Title\"; label = \"\"; initial_focus = \"Edit\"; spacer; : row { fixed_width = true; : column { width = 100; fixed_width = true; spacer; : text { key = \"Text\"; label = \"\"; }} : edit_box { key = \"Edit\"; edit_width = 20; fixed_width = true; is_default = true; }} spacer; ok_cancel; }" fn)
    (close fn)
    t
  )

  (defun run_editbox_dcl ( dcl_id / r )
    (if (new_dialog "EditBox" dcl_id)
      (progn
        (set_tile "Title" "Specific non fungible characteristic of filenames to be processed - considered in pattern matching search")
        (set_tile "Text" "Specify pattern describing specific non fungible characteristic to be used for processing/collecting filenames - ENTER FOR ALL (\"*.*\")")
        (set_tile "Edit" "*.*")
        (action_tile "Edit" "(setq filter $value)") ;;; storing dialog input in variable "filter"...
        (action_tile "accept" "(done_dialog 1)")
        (action_tile "cancel" "(done_dialog 0)")
        (if (setq r (start_dialog))
          (progn
            (unload_dialog dcl_id)
            (if (zerop r)
              (setq filter nil)
              filter
            )
          )
        )
      )
    )
  )


  ;;; MAIN ROUTINE...

  ;;; INPUT DATA...

  (or
    (and
      (setq tmp_dcl_filename (vl-filename-mktemp "e_box" (car (LM:str->lst (vla-get-supportpath (vla-get-files (vla-get-preferences (vlax-get-acad-object)))) ";")) ".dcl"))
      (editbox_makedcl tmp_dcl_filename)
      (> (setq dcl_id (load_dialog tmp_dcl_filename)) 0)
      (or (setq filter (run_editbox_dcl dcl_id)) t)
      (or
        (if (findfile tmp_dcl_filename)
          (vl-file-delete tmp_dcl_filename)
        )
        t
      )
      filter
    )
    (and
      (> (setq han (load_dialog "acad")) 0)
      (setq filter (LM:editbox "Specify pattern describing specific non fungible characteristic to be used for processing/collecting filenames - ENTER FOR ALL (\"*.*\")" han))
    )
    (setq filter (dos_editbox "Specific non fungible characteristic of filenames to be processed - considered in pattern matching search" "Specify pattern for processing/collecting filenames - ENTER FOR ALL (\"*.*\")" "*.dwg"))
    (setq filter (getstring t "\nSpecify pattern describing specific non fungible characteristic to be used for processing/collecting filenames - ENTER FOR ALL (\"*.*\")\n\t:"))
  )
  (if (= "" filter)
    (setq filter "*.*")
  )

  (or
(not filter)
(setq folder (strcat (acet-ui-pickdir "Select folder tree to process wcmatch_pattern files matching...") "\\"))
(if (setq folder (getfiled "Select folder tree to process wcmatch_pattern files matching... Then just pick one of files and press OPEN button" "\\" filter 16))
(setq folder (car (fnsplitl folder)))
)
(setq folder (dos_getdir "Browse for folder" "\\" "Select folder tree to process wcmatch_pattern files matching..."))
(if (setq folder (dos_getfiled "Browse for folder - Select folder tree to process wcmatch_pattern files matching..." "\\" ""))
(setq folder (car (fnsplitl folder)))
)
(setq folder (car (dos_getfilenav "Browse for folder - Select folder tree to process wcmatch_pattern files matching..." "\\" filter 4096))) ;;; 4096 (bit 12) - multiple file seletion enabled
) ;;; MAIN PROCESSING ... (if (and folder filter (or (setq fullfilenames (_findfiles folder filter)) (setq fullfilenames (LM:directoryfiles-main folder filter t)))) (progn (setq filenames (mapcar (function (lambda ( x / y ) (setq y (fnsplitl x)) (strcat (cadr y) (caddr y)))) fullfilenames)) (setq *pattern* (mainprocess filenames)) (prompt "\nSpecified pattern that was used for processing : \"") (prompt filter) (prompt "\"") (prompt "\nSpecified folder that was used for processing : \"") (prompt folder) (prompt "\"") (prompt "\n") (prompt "\nProcessed total : ") (princ (if filenames (length filenames) 0)) (prompt " filenames...") (prompt "\n") (prompt "\nCOMMON WCMATCH PATTERN / MATCHING STRINGS FILTER SPECIFICATION : \"") (prompt *pattern*) (prompt "\"") (prompt "\n") (prompt "\nPattern is stored in global variable : \"*pattern*\"... You can call it with : !*pattern*...") ) (cond ( (and folder filter) (prompt "\nSorry, you picked empty folder tree - there are no files matching specified pattern that was used for processing...") (prompt "\nSpecified pattern that was used for processing : \"") (prompt filter) (prompt "\"") (prompt "\nSpecified folder that was used for processing : \"") (prompt folder) (prompt "\"") (prompt "\n\nPossible problem : invalid filenames - used bad code page in naming them (collecting of files not processed - (vl-directory-files) bug...\nEither use differnt pattern, or pick diferent folder tree next time...") ) ( folder (prompt "\nSpecified folder that was used for processing : \"") (prompt folder) (prompt "\"") (prompt "\n") (prompt "\nInvalid input - pattern that is to be used for processing havent been defined sucessfully...") (prompt "\n\nTry to fix problem of not invoking DCL dialog box by debugging (load_dialog) function on specified string at beginning of temporary DCL file... \nIf value is positive number, then you should look for next issue that causes not starting edit box input...") (prompt "\nAlternatively you can try some differnt method of invoking edit box input : DosLib function (dos_editbox)...") ) ( filter (prompt "\nSpecified pattern that was used for processing : \"") (prompt filter) (prompt "\"") (prompt "\n") (prompt "\nEither (acet-ui-pickdir) haven't initialized properly, or you pressed CANCEL button when dialog box for selecting folder appeared, or you terminated proper way of routine execution...") (prompt "\n\nTry to replace (acet-ui-pickdir) method of invoking dialog box for folder selection with some different approach : (getfiled) function; DosLib function (dos_getdir)...") ) ( t (prompt "\nNothing processed... And no valid input data...") (prompt "\n\nTry to fix problem of not invoking DCL dialog box by debugging (load_dialog) function on specified string at beginning of temporary DCL file... \nIf value is positive number, then you should look for next issue that causes not starting edit box input...") (prompt "\nEither (acet-ui-pickdir) haven't initialized properly, or you pressed CANCEL button when dialog box for selecting folder appeared, or you terminated proper way of routine execution...") (prompt "\n\nTry to replace (acet-ui-pickdir) method of invoking dialog box for folder selection with some different approach : (getfiled) function; DosLib function (dos_getdir)...") ) ) ) (textscr) (princ) )

 

;;; THIS EXAMPLES THAT FOLLOW COULD BE USEFUL FOR RESEARCH/STUDY TOO; THEY ARE ALSO SOMEHOW RELATED TO THIS TOPIC - (wcmatch) PATTERNS AND (wcmatch) FUNCTION ;;;

(defun LM-MR:wcmatchx ( str pat / MR:wcmatchx LM:wcmatchx )

  (defun MR:wcmatchx ( str pat / k )
    (setq k 0)
    (while (and (wcmatch (substr str 1 (setq k (1+ k))) pat) (/= k (strlen str))))
    (cond
      ( (and (wcmatch (substr str k) pat) (= k 1) (/= (substr pat 1 1) "~"))
        str
      )
      ( (and (= (substr str (1+ k)) "") (= (substr pat 1 1) "~") (= str (substr pat 2)))
        nil
      )
      ( (= (substr str (1+ k)) "")
        str
      )
      ( (wcmatch (substr str (1+ k)) pat)
        (substr str (1+ k))
      )
    )
  )

  (defun LM:wcmatchx ( str pat )
    (if (and (wcmatch str pat) (/= "" str))
      (cond
        ( (LM:wcmatchx (substr str 2) pat))
        ( (LM:wcmatchx (substr str 1 (1- (strlen str))) pat))
        ( str )
      )
    )
  )

  (cond
    ( (= pat "*")
      str
    )
    ( (or (= (substr pat 1 1) "*") (= (substr pat (strlen pat)) "*"))
      (LM:wcmatchx str pat)
    )
    ( t
      (MR:wcmatchx str pat)
    )
  )
)

(print (LM-MR:wcmatchx "abc123def" "*")) ;;; "abc123def"
(print (LM-MR:wcmatchx "abc123def" "*123*")) ;;; "123"
(print (LM-MR:wcmatchx "abc123def" "~abc")) ;;; "123def"
(print (LM-MR:wcmatchx "abc123def" "~123")) ;;; "abc123def"
(print (LM-MR:wcmatchx "abc123def" "*###*")) ;;; "123"
(print (LM-MR:wcmatchx "abc123def" "*123def")) ;;; "123def"
(print (LM-MR:wcmatchx "abc123def" "abc123*")) ;;; "abc123"
(print (LM-MR:wcmatchx "abc123def" "Jonathan")) ;;; nil
(princ)

 

But, still, when I do testings with my main (str1mchstr2) function, when processed main routine, almost always I get matching pattern result as : "*"...

Now I don't know what is the problem, but I am guessing that when list of matched patterns, match with each other (through recursion), result is reducing all the ways - finally producing : "*" as a result... Perhaps, the problem is that "*" character that occurs after first matching pass is treated like all other normal characters - not wild card - probably that causes shrinking of results; and when shrinked pass results/patterns recursive pass all to termination - (list with single pattern resulting string was processed) - result is "*" almost always...

 

Well, that's all from me till now...

We'll see how will progress further researching...

 

Regards, M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 12 of 29

john.uhden
Mentor
Mentor

@marko_ribar 

That's a lot of work for what I came up with in about 2 secs... "*"

@pbejse 

Is one of your rules that the strlens must match?

That could reduce the possibilities quickly, though this challenge feels like trying to translate Sanskrit to Swahili, whatever they are/were.  I think we may need to bring Ben Gates' mother (Helen Mirren) into this, though I'd rather bring in Abigail Chase (Diane Kruger).  I'd love to wcmatch with her.

John F. Uhden

0 Likes
Message 13 of 29

Sea-Haven
Mentor
Mentor

I can see using something like this making maybe a new list that has each item broken down even further into deeper list ("LEW" "-" "SD" "-" "YEE" "-" "SW" ..........)

 

 

This would using multiple lists remove odd items in list

 

 

 

; By Gile very helpful
(defun remove_doubles (lst)
  (if lst
    (cons (car lst) (remove_doubles (vl-remove (car lst) lst)))
  )
)

(setq lst '("LEW-SD-YEE-SW-LA-LY-20092.dwg" "LEW-SD-YEE-SW-LA-LY-10092.dwg"
	    "XX_LEW-SD-YEE-SW-LA-LY-10092.dwg" "LEW-SD-YEE-SS-AR-LY-20102.dwg"
	    "LEW-SD-YEE-SS-AR-L1-50092.dwg" "LEW-SD-YEE-SS-AR-L1-50092_recover.dwg"
	    "LEW-SD-YEE-SS-AR-LY-01110.dwg" "From Ground Floor.dwg"
	    "LEW-SD-YEE-SS-AR-LY-01100_latest.dwg"))
		
(setq lst2 '())
(foreach val lst
(setq lst2 (cons (substr val 1 3) lst2))
)

(setq lst2 (remove_doubles lst2))
("LEW" "Fro" "LEW" "LEW" "LEW" "LEW" "XX_" "LEW" "LEW")

("LEW" "Fro" "XX_")
; pop list in dcl and choose 1
delete from master list the not chosen and add a next item do again.

 

 

 

If list after remove has only 1 item then skip, till say 2 or more. So it would stop at LEW-SD-YEE-SS- as more than 1 pattern.

Of course the "-" "_" and a space complicates in dwg name.

0 Likes
Message 14 of 29

pbejse
Mentor
Mentor

@john.uhden wrote:

Is one of your rules that the strlens must match?


That is essential in bringing down the number of possibilities.  The length is supposed to be the same  of course.

 


@john.uhden wrote:

So, the challenge is to find/build a pattern that matches most of the items without a simple "*" ?

But that could be just "???-????-???? etc."


Yes, but that would spit out  misleading results.

From this list

(setq lst '("LEW-SD-YEE-00-AR-LY-01111.dwg"
	    "LEW-SD-YEE-SW-LA-LY-20092.dwg"
	    "LEW-SD-YEE-SW-LA-LY-10092.dwg"
	    "LEW-SD-YEE-SS-AR-L1-50092.dwg"
	    "LEW-SD-YEE-SS-AR-L1-50092_recover.dwg"
	    "LEW-SD-YEE-SS-AR-LY-20102.dwg"
	    "From Ground Floor.dwg"
	    "LEW-SD-YEE-SS-AR-LY-01100_latest.dwg"
	    "LEW-SD-YEE-SS-AR-LY-01110.dwg"
	    "LEW-SD-YEE-SS-AR-LY-1124X.dwg"
	    "LEW-SD-YEE-SS-0#-LY-1124X.dwg"
	   )
)

Following this rule from post # 1 "if  A pattern appears more than 3 times, then it should be included on the list"

Using this filter ("???-??-???-??-??-??-?????.dwg") will give you

"LEW-SD-YEE-00-AR-LY-01111.dwg" 
"LEW-SD-YEE-SW-LA-LY-20092.dwg" 
"LEW-SD-YEE-SW-LA-LY-10092.dwg" 
"LEW-SD-YEE-SS-AR-L1-50092.dwg" "LEW-SD-YEE-SS-AR-LY-20102.dwg" "LEW-SD-YEE-SS-AR-LY-01110.dwg" "LEW-SD-YEE-SS-AR-LY-1124X.dwg" "LEW-SD-YEE-SS-0#-LY-1124X.dwg"

While with this filter ("LEW-SD-YEE-@@-@@-L@-#####.dwg")

"LEW-SD-YEE-SW-LA-LY-20092.dwg" 
"LEW-SD-YEE-SW-LA-LY-10092.dwg" 
"LEW-SD-YEE-SS-AR-LY-20102.dwg" 
"LEW-SD-YEE-SS-AR-LY-01110.dwg" 

HTH


@john.uhden wrote:

I think we may need to bring Ben Gates' mother (Helen Mirren) into this, though I'd rather bring in Abigail Chase (Diane Kruger).  I'd love to wcmatch with her.


😂 

The Cage's mum and archivist girlfriend is a good choice @john.uhden, but I'll do you one better,

What if we bring in See-Threepio for this. 

I am fluent in over six million forms of communication.” - 

 

0 Likes
Message 15 of 29

Sea-Haven
Mentor
Mentor

Is See-Threepio  3-cpo's cousin ?

 

SeaHaven_0-1645418747810.png

 

0 Likes
Message 16 of 29

pbejse
Mentor
Mentor

@marko_ribar wrote:

Greetings...

I took some of my free hours to arrange posted sub functions that could be useful for this challenge task...

...

Well, that's all from me till now...

We'll see how will progress further researching...


Thank you for all the hard work @marko_ribar,  That is a lot to digest, I'll go through the code later today.

 

Cheers

 

0 Likes
Message 17 of 29

pbejse
Mentor
Mentor

@Sea-Haven wrote:

Is See-Threepio  3-cpo's cousin ?

Actually one and the same @Sea-Haven. All red arm and Silver leg to go with it.

 


@Sea-Haven wrote:

This would using multiple lists remove odd items in list..


That is an intersting approach. What i ended up using is a _retain_doubles_or_more kind of sub.

Thank you for your particaption @Sea-Haven 👍

 

I'm almost done and will post the draft later today.

 

 

 

0 Likes
Message 18 of 29

marko_ribar
Advisor
Advisor
Accepted solution

I have something better solution than prvious attempt...

 

I've changed main sub (str1mchstr2) - now it's more understandable and I hope better... Actually ther are 2 types of them : one is "general" - using wild card char (*), and the other one is "special" - your type of sophisticated using (#,@,?) - here "." that occurs in (wcmatch) description IMHO is better used as "?" (everything else - meaning no alphanumeric, just like "." (real meaning of "?" is like it was - every character no matter if alphanumeric or not, but here it actually behaves like ".", as "#" and "@" have precedence))...

 

;;; USED GENERAL NON COMMAND FUNCTIONS ;;;

;;; pattern matching between 2 strings ;;;
;;; https://www.cadtutor.net/forum/topic/74031-matching-pattern-of-two-strings/

(defun str1mchstr2-general ( str1 str2 / unique* l1 l2 a r )

  (defun unique* ( l / a r )
    (while (setq a (car l))
      (if (and (= a 42) (vl-position 42 (cdr l)))
        (setq r (cons a r)
              l (member (vl-some (function (lambda ( x ) (if (/= x 42) x))) l) l)
        )
        (setq r (cons a r)
              l (cdr l)
        )
      )
    )
    (reverse r)
  )

  (setq l1 (vl-string->list str1))
  (setq l2 (vl-string->list str2))
  (if (> (length l1) (length l2))
    (mapcar (function set) '(l1 l2) (list l2 l1))
  )
  (while (setq a (car l1))
    (cond
      ( (= a (car l2))
        (setq r (cons a r)
              l2 (cdr l2)
        )
      )
      ( (and (vl-position a (cdr l2)) (>= (length (member a l2)) (length l1)))
        (setq r (cons a r)
              l2 (cdr (member a l2))
        )
      )
      ( t
        (setq r (cons 42 r)
              l2 (cdr l2)
        )
      )
    )
    (setq l1 (cdr l1))
  )
  (if l2
    (setq r (cons 42 r))
  )
  (vl-list->string (unique* (reverse r)))
)

;;;
;;; (defun c:ttt1 nil (str1mchstr2-general "Drawing_12_1297-2241079-LEVEL 50 - PRESSURE SERVICES - ZONE 3" "Drawing_6_1303-2241073-LEVEL 50 - PRESSURE SERVICES - ZONE 3"))
;;; (defun c:ttt2 nil (str1mchstr2-general "Drawing_6_1303-2241073-LEVEL 50 - PRESSURE SERVICES - ZONE 3" "Drawing_12_1297-2241079-LEVEL 50 - PRESSURE SERVICES - ZONE 3"))
;;;
;;; "Drawing_*_1*-224107*-LEVEL 50 - PRESSURE SERVICES - ZONE 3" ;;;

;;; pattern matching between 2 strings ;;;
;;; https://www.cadtutor.net/forum/topic/74031-matching-pattern-of-two-strings/

(defun str1mchstr2-special ( str1 str2 / unique-n l1 l2 a r )

;; sub function is needless, but I'll leve it just in case, you'll need it for uniquing special char ; n - ascii value of character
;|
  (defun unique-n ( n l / a r )
    (while (setq a (car l))
      (if (and (= a n) (vl-position n (cdr l)))
        (setq r (cons a r)
              l (member (vl-some (function (lambda ( x ) (if (/= x n) x))) l) l)
        )
        (setq r (cons a r)
              l (cdr l)
        )
      )
    )
    (reverse r)
  )
|;

  (setq l1 (vl-string->list str1))
  (setq l2 (vl-string->list str2))
  (if (> (length l1) (length l2))
    (mapcar (function set) '(l1 l2) (list l2 l1))
  )
  (while (setq a (car l1))
    (cond
      ( (= a (car l2))
        (setq r (cons a r))
      )
      ( (and (< 47 a 58) (< 47 (car l2) 58))
        (setq r (cons 35 r))
      )
      ( (or (and (< 64 a 91) (< 64 (car l2) 91)) (and (< 96 a 123) (< 96 (car l2) 123)))
        (setq r (cons 64 r))
      )
      ( t
        (setq r (cons 63 r))
      )
    )
    (setq l1 (cdr l1))
    (setq l2 (cdr l2))
  )
  (if l2
    (foreach x l2
      (setq r (cons 63 r))
    )
  )
  (vl-list->string (reverse r))
)

;;;
;;; (defun c:ttt1 nil (str1mchstr2-special "Drawing_12_1297-2241079-LEVEL 50 - PRESSURE SERVICES - ZONE 3" "Drawing_6_1303-2241073-LEVEL 50 - PRESSURE SERVICES - ZONE 3"))
;;; (defun c:ttt2 nil (str1mchstr2-special "Drawing_6_1303-2241073-LEVEL 50 - PRESSURE SERVICES - ZONE 3" "Drawing_12_1297-2241079-LEVEL 50 - PRESSURE SERVICES - ZONE 3"))
;;; 
;;; "Drawing_#??###??2#####??@@@@??#????@@@S@@@??@@@@@@@????@@@???" ;;;

;;; process list with filenames-patterns by collecting each matching pattern (each string pair matching) and finally removing duplicates - used method : iteration ;;;
;;; filenameslist-patternslist - list with strings
;;; return - list with common matching pattern(s) string(s)

(defun process ( filenameslist-patternslist mode / unique resultpatterns )

  (defun unique ( l / a r )
    (while (setq a (car l))
      (if (vl-some (function (lambda ( x ) (equal a x))) (cdr l))
        (setq r (cons a r)
              l (vl-remove-if (function (lambda ( x ) (equal a x))) (cdr l))
        )
        (setq r (cons a r)
              l (cdr l)
        )
      )
    )
    (reverse r)
  )

  (setq filenameslist-patternslist (vl-sort filenameslist-patternslist (function (lambda ( a b ) (> (strlen a) (strlen b)))))) ;;; added this line - processing is shrinking results, so every pass, processing must be perfomed from longest strings to smaller...
  (foreach filename-pattern1 filenameslist-patternslist
    (setq filenameslist-patternslist (cdr filenameslist-patternslist))
    (foreach filename-pattern2 filenameslist-patternslist
      (setq resultpatterns (cons (if (= mode "1") (str1mchstr2-general filename-pattern1 filename-pattern2) (str1mchstr2-special filename-pattern1 filename-pattern2)) resultpatterns))
    )
  )
  (unique resultpatterns)
)

;;; process list with filenames strings until matched pattern(s) become sinlge common matching pattern string - used method : recursion ;;;
;;; filenameslist-patternslist - list with strings representing filenames specifications
;;; return - common matching pattern string

(defun mainprocess ( filenameslist-patternslist mode )
  (if (> (length filenameslist-patternslist) 1)
    (mainprocess (process filenameslist-patternslist mode) mode)
    (car filenameslist-patternslist)
  )
)

;;; collect list of filenames of all specific files residing in main/parent folder and all its sub/child folders ;;;
;;; libraryrootprefix - main/parent folder string
;;; filenamepattern - pattern describing specific non fungible characteristic to be used for processing/collecting filenames / nil ("*.*")
;;; return - list with filenames strings (full paths included) collected in specific folder tree that satisfy custom specific filter if it was provided and passed to evaluation

(defun _findfiles ( libraryrootprefix filenamepattern / subs processsubfolders folders fl r ) ;;; (_findfiles "F:\\ACAD ADDONS-NEW\\" "profile*.lsp")

  (defun subs ( folder )
    (vl-remove "." (vl-remove ".." (vl-directory-files folder nil -1)))
  )

  (defun processsubfolders ( rootfolder / subfolders )
    (setq subfolders (subs rootfolder))
    (foreach sub subfolders
      (if (= (substr rootfolder (strlen rootfolder)) "\\")
        (setq r (cons (strcat rootfolder sub) (processsubfolders (strcat rootfolder sub))))
        (setq r (cons (strcat rootfolder "\\" sub) (processsubfolders (strcat rootfolder "\\" sub))))
      )
    )
    r
  )

  (setq folders (append (list libraryrootprefix) (processsubfolders libraryrootprefix)))
  (foreach folder folders
    (foreach x (vl-directory-files folder filenamepattern 1)
      (setq fl (cons (strcat folder "\\" x) fl))
    )
  )
  (reverse fl)
)

;; Directory Files  -  Lee Mac
;; Retrieves all files of a specified filetype residing in a directory (and subdirectories)
;; dir - [str] Root directory for which to return filenames
;; typ - [str] Optional filetype filter (DOS pattern)
;; sub - [bol] If T, subdirectories of the root directory are included
;; Returns: [lst] List of files matching the filetype criteria, else nil if none are found

(defun LM:directoryfiles-main ( dir typ sub / LM:directoryfiles l ) ;;; why main function ? - purpose : clearing "l" variable (globals are not desirable in any case...)

  (defun LM:directoryfiles ( dir typ sub )
    (setq dir (vl-string-right-trim "\\" (vl-string-translate "/" "\\" dir)))
    (mapcar
      (function
        (lambda ( x )
          (setq l (append l (list (strcat dir "\\" x))))
        )
      ) (vl-directory-files dir typ 1)
    )
    (if sub
      (mapcar
        (function
          (lambda ( x )
            (if (not (wcmatch x "`.,`.`."))
              (LM:directoryfiles (strcat dir "\\" x) typ sub)
            )
          )
        )
        (vl-directory-files dir nil -1)
      )
    )
  )

  (LM:directoryfiles dir typ sub)
  l
)

;;; MAIN ROUTINE ;;;

;;;------------------------------------------------------------------------------------------------------------------------;;;
;;;                                                                                                                        ;;;
;;; FIND COMMON MATCHING PATTERN STRING OF ALL SPECIFIC FILES RESIDING IN MAIN/PARENT FOLDER AND ALL ITS SUB/CHILD FOLDERS ;;;
;;;                                                                                                                        ;;;
;;; By Marko Ribar, d.i.a. (architect) : 20.02.2022.                                                                       ;;;
;;;                                                                                                                        ;;;
;;;------------------------------------------------------------------------------------------------------------------------;;;

(defun c:folder_wcmatch_pattern ( / *error* LM:str->lst LM:editbox editbox_makedcl run_editbox_dcl tmp_dcl_filename dcl_id han filter folder fullfilenames filenames mode )

  (vl-load-com) ;;; load AciveX extensions (VLA-functions)...

  ;;; HELPER SUB FUNCTIONS...

  (defun *error* ( m )
    (vl-catch-all-apply 'term_dialog nil)
    (if m
      (prompt m)
    )
    (princ)
  )

  ;; String to List  -  Lee Mac
  ;; Separates a string using a given delimiter
  ;; str - [str] String to process
  ;; del - [str] Delimiter by which to separate the string
  ;; Returns: [lst] List of strings

  (defun LM:str->lst ( str del / len lst pos )
    (setq len (1+ (strlen del)))
    (while (setq pos (vl-string-search del str))
      (setq lst (cons (substr str 1 pos) lst)
            str (substr str (+ pos len))
      )
    )
    (reverse (cons str lst))
  )

  ;; Edit Box  -  Lee Mac
  ;; Displays a DCL Edit Box to obtain a string from the user
  ;; str - [str] Initial value to display ("" for none)
  ;; Returns: [str] Edit box contents if user pressed OK, else nil

  (defun LM:editbox ( str han )
    (if (new_dialog  "acad_txtedit" han)
      (progn
        (set_tile    "text_edit"    str)
        (action_tile "text_edit" "(setq str $value)")
        (if (zerop (start_dialog))
          (setq str nil)
        )
        (if (and han (< 0 han))
          (unload_dialog han)
        )
        str
      )
    )
  )

  (defun editbox_makedcl ( fullfilename / fn )
    (setq fn (open fullfilename "w"))
    (write-line "EditBox : dialog { key = \"Title\"; label = \"\"; initial_focus = \"Edit\"; spacer; : row { fixed_width = true; : column { width = 100; fixed_width = true; spacer; : text { key = \"Text\"; label = \"\"; }} : edit_box { key = \"Edit\"; edit_width = 20; fixed_width = true; is_default = true; }} spacer; ok_cancel; }" fn)
    (close fn)
    t
  )

  (defun run_editbox_dcl ( dcl_id / r )
    (if (new_dialog "EditBox" dcl_id)
      (progn
        (set_tile "Title" "Specific non fungible characteristic of filenames to be processed - considered in pattern matching search")
        (set_tile "Text" "Specify pattern describing specific non fungible characteristic to be used for processing/collecting filenames - ENTER FOR ALL (\"*.*\")")
        (set_tile "Edit" "*.*")
        (action_tile "Edit" "(setq filter $value)") ;;; storing dialog input in variable "filter"...
        (action_tile "accept" "(done_dialog 1)")
        (action_tile "cancel" "(done_dialog 0)")
        (if (setq r (start_dialog))
          (progn
            (unload_dialog dcl_id)
            (if (zerop r)
              (setq filter nil)
              filter
            )
          )
        )
      )
    )
  )


  ;;; MAIN ROUTINE...

  ;;; INPUT DATA...

  (initget "1 2 3")
  (setq mode (getkword "\nChoose desired matching pattern style [ 1. wild card used (*) / 2. special character used / 3. both results ] <3> : "))
  (if (not mode)
    (setq mode "3")
  )

  (or
    (and
      (setq tmp_dcl_filename (vl-filename-mktemp "e_box" (car (LM:str->lst (vla-get-supportpath (vla-get-files (vla-get-preferences (vlax-get-acad-object)))) ";")) ".dcl"))
      (editbox_makedcl tmp_dcl_filename)
      (> (setq dcl_id (load_dialog tmp_dcl_filename)) 0)
      (or (setq filter (run_editbox_dcl dcl_id)) t)
      (or
        (if (findfile tmp_dcl_filename)
          (vl-file-delete tmp_dcl_filename)
        )
        t
      )
      filter
    )
    (and
      (> (setq han (load_dialog "acad")) 0)
      (setq filter (LM:editbox "Specify pattern describing specific non fungible characteristic to be used for processing/collecting filenames - ENTER FOR ALL (\"*.*\")" han))
    )
    (setq filter (dos_editbox "Specific non fungible characteristic of filenames to be processed - considered in pattern matching search" "Specify pattern for processing/collecting filenames - ENTER FOR ALL (\"*.*\")" "*.dwg"))
    (setq filter (getstring t "\nSpecify pattern describing specific non fungible characteristic to be used for processing/collecting filenames - ENTER FOR ALL (\"*.*\")\n\t:"))
  )
  (if (= "" filter)
    (setq filter "*.*")
  )

  (or
(not filter)
(setq folder (strcat (acet-ui-pickdir "Select folder tree to process wcmatch_pattern files matching...") "\\"))
(if (setq folder (getfiled "Select folder tree to process wcmatch_pattern files matching... Then just pick one of files and press OPEN button" "\\" filter 16))
(setq folder (car (fnsplitl folder)))
)
(setq folder (dos_getdir "Browse for folder" "\\" "Select folder tree to process wcmatch_pattern files matching..."))
(if (setq folder (dos_getfiled "Browse for folder - Select folder tree to process wcmatch_pattern files matching..." "\\" ""))
(setq folder (car (fnsplitl folder)))
)
(setq folder (car (dos_getfilenav "Browse for folder - Select folder tree to process wcmatch_pattern files matching..." "\\" filter 4096))) ;;; 4096 (bit 12) - multiple file seletion enabled
) ;;; MAIN PROCESSING ... (if (and folder filter (or (setq fullfilenames (_findfiles folder filter)) (setq fullfilenames (LM:directoryfiles-main folder filter t)))) (progn (setq filenames (mapcar (function (lambda ( x / y ) (setq y (fnsplitl x)) (strcat (cadr y) (caddr y)))) fullfilenames)) (cond ( (= mode "1") (setq *pattern-general* (mainprocess filenames "1")) ) ( (= mode "2") (setq *pattern-special* (mainprocess filenames "2")) ) ( t (setq *pattern-general* (mainprocess filenames "1")) (setq *pattern-special* (mainprocess filenames "2")) ) ) (cond ( (= mode "1") (prompt "\nSpecified pattern that was used for processing : \"") (prompt filter) (prompt "\"") (prompt "\nSpecified folder that was used for processing : \"") (prompt folder) (prompt "\"") (prompt "\n") (prompt "\nProcessed total : ") (princ (if filenames (length filenames) 0)) (prompt " filenames...") (prompt "\n") (prompt "\nCOMMON WCMATCH PATTERN / MATCHING STRINGS FILTER SPECIFICATION - GENERAL - USED WILD CARD CHARACTER (*) : \"") (prompt *pattern-general*) (prompt "\"") (prompt "\n") (prompt "\nPattern is stored in global variable : \"*pattern-general*\"... You can call it with : !*pattern-general*...") ) ( (= mode "2") (prompt "\nSpecified pattern that was used for processing : \"") (prompt filter) (prompt "\"") (prompt "\nSpecified folder that was used for processing : \"") (prompt folder) (prompt "\"") (prompt "\n") (prompt "\nProcessed total : ") (princ (if filenames (length filenames) 0)) (prompt " filenames...") (prompt "\n") (prompt "\nCOMMON WCMATCH PATTERN / MATCHING STRINGS FILTER SPECIFICATION - SPECIAL : \"") (prompt *pattern-special*) (prompt "\"") (prompt "\n") (prompt "\nPattern is stored in global variable : \"*pattern-special*\"... You can call it with : !*pattern-special*...") ) ( t (prompt "\nSpecified pattern that was used for processing : \"") (prompt filter) (prompt "\"") (prompt "\nSpecified folder that was used for processing : \"") (prompt folder) (prompt "\"") (prompt "\n") (prompt "\nProcessed total : ") (princ (if filenames (length filenames) 0)) (prompt " filenames...") (prompt "\n") (prompt "\nCOMMON WCMATCH PATTERN / MATCHING STRINGS FILTER SPECIFICATION - GENERAL - USED WILD CARD CHARACTER (*) : \"") (prompt *pattern-general*) (prompt "\"") (prompt "\nCOMMON WCMATCH PATTERN / MATCHING STRINGS FILTER SPECIFICATION - SPECIAL : \"") (prompt *pattern-special*) (prompt "\"") (prompt "\n") (prompt "\nPatterns are stored in global variables : \"*pattern-general*\" and \"*pattern-special*\"... You can call them with : !*pattern-general* or !*pattern-special*...") ) ) ) (cond ( (and folder filter) (prompt "\nSorry, you picked empty folder tree - there are no files matching specified pattern that was used for processing...") (prompt "\nSpecified pattern that was used for processing : \"") (prompt filter) (prompt "\"") (prompt "\nSpecified folder that was used for processing : \"") (prompt folder) (prompt "\"") (prompt "\n\nPossible problem : invalid filenames - used bad code page in naming them (collecting of files not processed - (vl-directory-files) bug...\nEither use differnt pattern, or pick diferent folder tree next time...") ) ( folder (prompt "\nSpecified folder that was used for processing : \"") (prompt folder) (prompt "\"") (prompt "\n") (prompt "\nInvalid input - pattern that is to be used for processing havent been defined sucessfully...") (prompt "\n\nTry to fix problem of not invoking DCL dialog box by debugging (load_dialog) function on specified string at beginning of temporary DCL file... \nIf value is positive number, then you should look for next issue that causes not starting edit box input...") (prompt "\nAlternatively you can try some differnt method of invoking edit box input : DosLib function (dos_editbox)...") ) ( filter (prompt "\nSpecified pattern that was used for processing : \"") (prompt filter) (prompt "\"") (prompt "\n") (prompt "\nEither (acet-ui-pickdir) haven't initialized properly, or you pressed CANCEL button when dialog box for selecting folder appeared, or you terminated proper way of routine execution...") (prompt "\n\nTry to replace (acet-ui-pickdir) method of invoking dialog box for folder selection with some different approach : (getfiled) function; DosLib function (dos_getdir)...") ) ( t (prompt "\nNothing processed... And no valid input data...") (prompt "\n\nTry to fix problem of not invoking DCL dialog box by debugging (load_dialog) function on specified string at beginning of temporary DCL file... \nIf value is positive number, then you should look for next issue that causes not starting edit box input...") (prompt "\nEither (acet-ui-pickdir) haven't initialized properly, or you pressed CANCEL button when dialog box for selecting folder appeared, or you terminated proper way of routine execution...") (prompt "\n\nTry to replace (acet-ui-pickdir) method of invoking dialog box for folder selection with some different approach : (getfiled) function; DosLib function (dos_getdir)...") ) ) ) (textscr) (princ) )

 

Regards, M.R.

P.S. I hopefully solved problems with DCL inputs...

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 19 of 29

pbejse
Mentor
Mentor
Accepted solution

Here you go:

Function: _FilterThisFilesForMe

 

(Defun _FilterThisFilesForMe ( lst / nlst a b c f passed)
(setq nlst 
	(mapcar '(lambda (fn / fn_)
		(setq fn_ (vl-filename-base fn))	   
			(foreach ptn '(("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
			       		"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
			     		("0123456789" "##########"))
	  			(setq fn_ (vl-string-translate (Car ptn)(cadr ptn) fn_)
					)
				  )
		   (list  fn_ (vl-filename-base fn))
		   	)
		lst
		)
      )
(while (setq a (car nlst))(setq b (Cdr nlst))
	(Setq x (Vl-remove-if-not '(lambda (d)
	(setq f (= (Car a)(car d)))
  		(and (null f)(setq c (Cons d c))) f )  b))
	(setq nlst c c nil)
  		(cond
		  ((null x))
		  ((< (length x) 3))
		  ( T (setq Passed (cons (cons a x) passed))))
  	)

 (mapcar '_GiveMeThePattern passed)
  )

 

Subfunction: _GiveMeThePattern

 

(defun _GiveMeThePattern (l / a AllPattern)
  (while (setq a (car l))
    	(setq b (cdr l) l b)
	(setq ThePatterns (mapcar '(lambda (r / Fname w p ps)
	       (setq p 0 Fname (Cadr a))
		(While (and
			 (< (+ p (Setq ps (Vl-string-mismatch (Cadr a) (Cadr r) p p)))
			   		(strlen Fname))) 
		  	(setq Fname (strcat (substr Fname 1 (+ p ps))
						(substr (Car a) (+ 1 ps p) 1)
							(substr Fname (+ 2 (+ p ps)))))
		  	(setq p (+ 1 p ps))
		   
		  ) Fname
	       )
	    b
	    )
	  )
    (setq AllPattern (cons ThePatterns AllPattern))    
    )
    (car (vl-sort (apply 'append AllPattern) '<))
    )

 

Let's give this a try:

(setq lst1 '("1396_000-ERT-LAS-DWG-ST03-00-1001.dwg"
	     "1396_000-ERT-LAS-DWG-ST03-00-1001_recover.dwg"
	     "1396_000-ERT-IRR-DWG-ST03-00-5002.dwg"
	     "1396_000-ERT-MEP-DWG-ST03-01-8001.dwg"
	     "1396_000-ERT-MEP-DWG-ST03-01-8112.dwg"
	     "1396_000-ERT-MEP-DWG-ST03-01-8112_xx.dwg"
	     "SCOPE OF WORK.dwg"
	     "Third floor.dwg"
	    )
)
(_FilterThisFilesForMe lst1)--->("1396_000-ERT-@@@-DWG-ST03-0#-####")
(setq lst2 '("LEW-SD-YEE-SW-LA-LY-20092.dwg"
	     "LEW-SD-YEE-SW-LA-LY-10092.dwg"
	     "XX_LEW-SD-YEE-SW-LA-LY-10092.dwg"
	     "LEW-SD-YEE-SS-AR-LY-20102.dwg"
	     "LEW-SD-YEE-SS-AR-L1-50092.dwg"
	     "LEW-SD-YEE-SS-AR-L1-50092_recover.dwg"
	     "LEW-SD-YEE-SS-AR-LY-01110.dwg"
	     "From Ground Floor.dwg"
	     "LEW-SD-YEE-SS-AR-LY-01100_latest.dwg"
	    )
)
(_FilterThisFilesForMe lst2)--->("LEW-SD-YEE-S@-@@-LY-#####")
(setq lst3 '("300612-22-A-101.dwg"
	     "300612-22-D-312.dwg"
	     "300612-22-D-313.dwg"
	     "300612-22-D-501.dwg"
	     "300612-22-D-313_updated.dwg"
	     "300612-22-X-01.dwg"
	     "300612-22-X-02.dwg"
	     "300612-22-X-10.dwg"
	     "300612-22-X-25.dwg"
	     "D-TEMPLATE.dwg"
	    )
)
(_FilterThisFilesForMe lst3)--->("300612-22-X-##" "300612-22-@-###")

What is missing here is the ".dwg" extension, but we can deal with that later.

Let me know what you guys think.

 

This is not the best code ,No.  this is just a tribute!  🙂

 

 

0 Likes
Message 20 of 29

marko_ribar
Advisor
Advisor

First part is pretty normal...

Second sub. is interesting...

You are using (vl-string-mismatch) function which I really never used in my carrer...

You are using (while) loop-ing inside (mapcar '(lambda ( ... ) ) ... ) loop-ing, which is pretty unusual...

 

This at the end :

(vl-sort (apply 'append AllPattern) '<)

 

On what is that '< refered [ string length , or perhaps list length ] ... I haven't followed returns all the way...

Why are you so condemned on condition : 3 or more matchings produce 1 pattern... Perhaps give a user a choice to choose complexity of processing - I suppose it's just altering that (cond) in first sub... What if you have list with only 2 filenames? Shouldn't you match all patterns finally to get one final resulting pattern...

 

I was doing this by recursion... But it's bad - it stals my CAD, and I have to terminate it...

 

All in all, pretty well done...

Congrats...

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes