Jump to content

FOREACH for LIST


ojacomarket

Recommended Posts

Dear friends,

 

The issue is:

 

I want to get selection set with ssget (specified by cons)

 

Then I want function FOREACH to check every entity from the list is there any entities that MATCH "*lp*" with command WCMATCH and if there are so draw a object on drawing (which is specified with entmake).

This one runs perfectly, BUT how to MATCH not only for "*lp*" but for (list "*lp*" "*kk*" "bet*"), so that EVERY entity from entget_data_from_selection_1 was checked by EVERY entity of another list of wcmatch.

I tried for mapcar, but mapcar require same sized list..

(defun c:qwerty ()
	(setq list_of_selections_1 (ssget "x" (list (cons 0 "TEXT") (cons 8 "Mootkood") (cons 7 "Standard"))))
(setq l_o_s_1_length (sslength list_of_selections_1))
	(setq number_1 (- 0 1))
(setq new_lili (list))
	(repeat l_o_s_1_length
(setq number_1 (1+ number_1))
	(setq entget_data_from_selection_1 (entget (ssname list_of_selections_1 number_1)))
(foreach x entget_data_from_selection_1 (setq p1 (car x)) (setq p2 (cdr x)) (if (and (= p1 1) (wcmatch p2 "*lp*")) (entmake (list (cons 0 "INSERT") (cons 8 "PUU") (cons 10 (cdr (assoc 11 entget_data_from_selection_1)))))))

u have ideas? :)

Edited by ojacomarket
Link to comment
Share on other sites

Replace the last line of your code (your foreach loop) with:

    (if (wcmatch (cdr (assoc 1 entget_data_from_selection_1)) "*lp*")
      (entmake (list '(0 . "INSERT") '(2 . <block_name_in_string>) '(8 . "PUU") (cons 10 (cdr (assoc 11 entget_data_from_selection_1))) '(41 . 1.0) '(42 . 1.0) '(43 . 1.0) '(50 . 0.0)))
      )

When drawing a block, you need to define the block name (2), scale (X,Y,Z : 41,42,43), and rotation (50) of the block... just like how you need the text height and text content for text.

If you don't give it a block name, how can AutoCAD possibly insert the block?

  • Thanks 1
Link to comment
Share on other sites

1 minute ago, Jonathan Handojo said:

Replace the last line of your code (your foreach loop) with:


    (if (wcmatch (cdr (assoc 1 entget_data_from_selection_1)) "*lp*")
      (entmake (list '(0 . "INSERT") '(2 . <block_name_in_string>) '(8 . "PUU") (cons 10 (cdr (assoc 11 entget_data_from_selection_1))) '(41 . 1.0) '(42 . 1.0) '(43 . 1.0) '(50 . 0.0)))
      )

When drawing a block, you need to define the block name (2), scale (X,Y,Z : 41,42,43), and rotation (50) of the block... just like how you need the text height and text content for text.

If you don't give it a block name, how can AutoCAD possibly insert the block?

Thank you Jonathan, as always your code works amazing, and actually I fixed that stuff, and edited this topic, for now I have issue to try match every entity from entget with another list (list "*lp*" "bet*" "*kk*")

Link to comment
Share on other sites

(wcmatch (cdr (assoc 1 entget_data_from_selection_1)) "*lp*,*kk*,bet*")

 

Edited by Jonathan Handojo
  • Thanks 1
Link to comment
Share on other sites

1 minute ago, Jonathan Handojo said:

(wcmatch (cdr (assoc 1 entget_data_from_selection_1)) "*lp*,*kk*,bet*)

 

Sorry, forgot to say,

I need it to match every entity from entget to wcmatch and if it is "*lp*" it draws one object if "*kk*" another object and so on..

I have very long code for that, is that possible to deal with foreach in that case?

Link to comment
Share on other sites

49 minutes ago, ojacomarket said:

Sorry, forgot to say,

I need it to match every entity from entget to wcmatch and if it is "*lp*" it draws one object if "*kk*" another object and so on..

I have very long code for that, is that possible to deal with foreach in that case?

 

Foreach is not the solution to everything. There are other ways to do it. For example:

 

Include this in the start of the code:

 

(setq pairs
	 '(
	   ("lp" . block_name1)
	   ("bet" . block_name2)
	   ("kk" . block_name3)
	   )
	)

 

And rather than replacing the original foreach in the forum with my previous code, replace the foreach with this instead:

 

    (vl-some
      '(lambda (x)
	 (if (wcmatch (cdr (assoc 1 entget_data_from_selection_1)) (strcat "*" (car x) "*"))
	   (entmake (list '(0 . "INSERT") (cons 2 (cdr x)) '(8 . "PUU") (cons 10 (cdr (assoc 11 entget_data_from_selection_1))) '(41 . 1.0) '(42 . 1.0) '(43 . 1.0) '(50 . 0.0)))
	   )
	 )
      pairs
      )

vl-some processes every element in the list with a function accepting one argument representing each element in the list (like x in foreach) (in the above case, it's "lambda"), and returns what the function will return resulting from the first element in the list that evaluates to anything other than nil to the function.

 

Once that happens, vl-some will stop processing the remainder of the list.

Edited by Jonathan Handojo
  • Thanks 1
Link to comment
Share on other sites

26 minutes ago, Jonathan Handojo said:

 

Foreach is not the solution to everything. There are other ways to do it. For example:

 

Include this in the start of the code:

 


(setq pairs
	 '(
	   ("lp" . block_name1)
	   ("bet" . block_name2)
	   ("kk" . block_name3)
	   )
	)

 

And rather than replacing the original foreach in the forum with my previous code, replace the foreach with this instead:

 


    (vl-some
      '(lambda (x)
	 (if (wcmatch (cdr (assoc 1 entget_data_from_selection_1)) (strcat "*" (car x) "*"))
	   (entmake (list '(0 . "INSERT") (cons 2 (cdr x)) '(8 . "PUU") (cons 10 (cdr (assoc 11 entget_data_from_selection_1))) '(41 . 1.0) '(42 . 1.0) '(43 . 1.0) '(50 . 0.0)))
	   )
	 )
      pairs
      )

vl-some processes every element in the list with a function accepting one argument representing each element in the list (like x in foreach) (in the above case, it's "lambda"), and returns the expression resulting from the first element in the list that evaluates to anything other than nil.

Very clear explanation!

Thank you for your amazing job!

Look, I got here also code made before but as again it doesn't show error but still doesn't ENTMAKE me, what I asked that code to do..

(defun c:qwerty ()
	(setq list_of_selections_1 (ssget "x" (list (cons 0 "TEXT") (cons 8 "Mootkood") (cons 7 "Standard"))))
(setq l_o_s_1_length (sslength list_of_selections_1))
	(setq number_1 (- 0 1))
	
(setq list_wcm
		  '(("*vp*" "INSERT" "VILJA1" "PUU")
		   ("*lp*" "INSERT" "LEHTP1" "PUU")
		   ("*mand*" "INSERT" "MAND1" "PUU")
))

(repeat l_o_s_1_length
	(setq number_1 (1+ number_1))

(setq entget_data_from_selection_1 (entget (ssname list_of_selections_1 number_1)))

	(foreach xx list_wcm (setq pp1 (car xx)) (if (wcmatch pp1 (cdr (assoc 1 entget_data_from_selection_1))) (entmake (list (cons 0 (nth 1 xx)) (cons 2 (nth 2 xx)) (cons 8 (nth 3 xx)) (cons 10 (cdr (assoc 11 (entget_data_from_selection_1)))) (cons 41 0.5) (cons 42 0.5) (cons 43 0.5) (cons 50 0.00)))))

	))

 

Link to comment
Share on other sites

16 minutes ago, ojacomarket said:

Very clear explanation!

Thank you for your amazing job!

Look, I got here also code made before but as again it doesn't show error but still doesn't ENTMAKE me, what I asked that code to do..


(defun c:qwerty ()
	(setq list_of_selections_1 (ssget "x" (list (cons 0 "TEXT") (cons 8 "Mootkood") (cons 7 "Standard"))))
(setq l_o_s_1_length (sslength list_of_selections_1))
	(setq number_1 (- 0 1))
	
(setq list_wcm
		  '(("*vp*" "INSERT" "VILJA1" "PUU")
		   ("*lp*" "INSERT" "LEHTP1" "PUU")
		   ("*mand*" "INSERT" "MAND1" "PUU")
))

(repeat l_o_s_1_length
	(setq number_1 (1+ number_1))

(setq entget_data_from_selection_1 (entget (ssname list_of_selections_1 number_1)))

	(foreach xx list_wcm (setq pp1 (car xx)) (if (wcmatch pp1 (cdr (assoc 1 entget_data_from_selection_1))) (entmake (list (cons 0 (nth 1 xx)) (cons 2 (nth 2 xx)) (cons 8 (nth 3 xx)) (cons 10 (cdr (assoc 11 (entget_data_from_selection_1)))) (cons 41 0.5) (cons 42 0.5) (cons 43 0.5) (cons 50 0.00)))))

	))

 

 

Turn your wcmatch around

  • Thanks 1
Link to comment
Share on other sites

3 minutes ago, Jonathan Handojo said:

 

Turn your wcmatch around

If you meant to change places of "pp1" "cdr (assoc...." so CAD gives syntax error...:(

Edited by ojacomarket
Link to comment
Share on other sites

4 minutes ago, ojacomarket said:

If you meant to change places of "pp1" "cdr (assoc...." so CAD gives syntax error...:(

 

like this... 

(wcmatch (cdr (assoc 1 entget_data_from_selection_1)) pp1)

 

Well, all the steps I posted here are not tested, mainly seen from pure eye, but it should work (from my eyes at least)

Edited by Jonathan Handojo
  • Confused 1
Link to comment
Share on other sites

2 minutes ago, Jonathan Handojo said:

 

like this... 


(wcmatch (cdr (assoc 1 entget_data_from_selection_1)) pp1)

 

Yeah, this string of code retrieves >
 

syntax error
Cannot invoke (command) from *error* without prior call to (*push-error-using-command*).
Converting (command) calls to (command-s) is recommended.

 

Link to comment
Share on other sites

13 minutes ago, ojacomarket said:

Yeah, this string of code retrieves >
 


syntax error
Cannot invoke (command) from *error* without prior call to (*push-error-using-command*).
Converting (command) calls to (command-s) is recommended.

 

I thought maybe there was problem with list of strings, but i changed it to form like that:

But nothing changed, codes loads without errors but no object (which are specified with entmake) are drawn...

(setq list_wcm
		  (list (list "*vp*" "INSERT" "VILJA1" "PUU")
		   (list "*lp*" "INSERT" "LEHTP1" "PUU")
		   (list "*mand*" "INSERT" "MAND1" "PUU")

 

Link to comment
Share on other sites

Let that be a lesson for you then... That's why it's best to include error-handling functions in the beginning of the code:

 

(defun *error* (msg) (princ (strcat "\nError: " msg)))

When a function fails from an error, the *error* function is executed. You can of course define your own *error* function to execute what to do if the function fails.

 

Next lesson, set all your variables local to the function. That way it won't mess up other functions containing the same variables. You know how, right?

 

(defun c:functionname ( / *error* list_wcm l_o_s_1_length ...)	; <--- Set local to the function
  (defun *error* (msg) (princ (strcat "\nError: " msg)))
  ;; Rest of code
  )

 

It's crucial that you set the *error* local to the function, because if you don't, then other functions that doesn't have the *error* function will call that very same function on fail.

 

As an added function, run the (*push-error-using-command*) command and proceed. Not that I know much about error-handling, so I'm in no position to be teaching you.

Edited by Jonathan Handojo
  • Thanks 1
Link to comment
Share on other sites

55 minutes ago, Jonathan Handojo said:

Let that be a lesson for you then... That's why it's best to include error-handling functions in the beginning of the code:

 


(defun *error* (msg) (princ (strcat "\nError: " msg)))

When a function fails from an error, the *error* function is executed. You can of course define your own *error* function to execute what to do if the function fails.

 

Next lesson, set all your variables local to the function. That way it won't mess up other functions containing the same variables. You know how, right?

 


(defun c:functionname ( / *error* list_wcm l_o_s_1_length ...)	; <--- Set local to the function
  (defun *error* (msg) (princ (strcat "\nError: " msg)))
  ;; Rest of code
  )

 

It's crucial that you set the *error* local to the function, because if you don't, then other functions that doesn't have the *error* function will call that very same function on fail.

 

As an added function, run the (*push-error-using-command*) command and proceed. Not that I know much about error-handling, so I'm in no position to be teaching you.

Thank you for this lesson, it is so nice, that you could explain those thing so perfectly, so even me understood, but it still doesn't execute, it writes "syntax error", but when i exclude those ...defun *error* stuff.. it writes as before "

syntax error
Cannot invoke (command) from *error* without prior call to (*push-error-using-command*).
Converting (command) calls to (command-s) is recommended.
Link to comment
Share on other sites

1 hour ago, Jonathan Handojo said:

Let that be a lesson for you then... That's why it's best to include error-handling functions in the beginning of the code:

 


(defun *error* (msg) (princ (strcat "\nError: " msg)))

When a function fails from an error, the *error* function is executed. You can of course define your own *error* function to execute what to do if the function fails.

 

Next lesson, set all your variables local to the function. That way it won't mess up other functions containing the same variables. You know how, right?

 


(defun c:functionname ( / *error* list_wcm l_o_s_1_length ...)	; <--- Set local to the function
  (defun *error* (msg) (princ (strcat "\nError: " msg)))
  ;; Rest of code
  )

 

It's crucial that you set the *error* local to the function, because if you don't, then other functions that doesn't have the *error* function will call that very same function on fail.

 

As an added function, run the (*push-error-using-command*) command and proceed. Not that I know much about error-handling, so I'm in no position to be teaching you.

As I understood it wrote "syntax error" it is now message for me, that code doesn;t apply beacause of syntax error, and the only possible error in my code is "(wcmatch (cdr (assoc.... pp1", when it is written like that it gives syntax error (if i have defun *error* at the beginning, if not it gives "cannot invoke..." as I wrote above).

When (wcmatch pp1 (cdr (assoc......) it executes, BUT nothing appear on screen in CAD, but it should write object at specified places...:(

(defun c:qwerty ( / *error* list_of_selections_1 l_o_s_1_length list_wcm number_1 entget_data_from_selection_1 pp1 pp2 pp3 pp4 xx)
	(defun *error* (msg) (princ (strcat "\nError: " msg)))
(setq list_of_selections_1 (ssget "x" (list (cons 0 "TEXT") (cons 8 "Mootkood") (cons 7 "Standard"))))
	(setq l_o_s_1_length (sslength list_of_selections_1))
(setq number_1 (- 0 1))
	(setq list_wcm
			  	 (list (list "*vp*" "INSERT" "VILJA1" "PUU")
		  	 	 (list "*lp*" "INSERT" "LEHTP1" "PUU")
			  	 (list "*mand*" "INSERT" "MAND1" "PUU")
))

(repeat l_o_s_1_length
	(setq number_1 (1+ number_1))

(setq entget_data_from_selection_1 (entget (ssname list_of_selections_1 number_1)))

	(foreach xx list_wcm (setq pp1 (car xx)) (setq pp2 (cadr xx)) (setq pp3 (caddr xx)) (setq pp4 (caddr (cdr xx))) (if (wcmatch pp1 (cdr (assoc 1 entget_data_from_selection_1))) (entmake (list (cons 0 pp2) (cons 2 pp3) (cons 8 pp4) (cons 10 (cdr (assoc 11 (entget_data_from_selection_1)))) (cons 41 0.5) (cons 42 0.5) (cons 43 0.5) (cons 50 0.00)))))
    
(princ)
	)
	)

 

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...