MAPCAR optimization

MAPCAR optimization

Browning_Zed
Advocate Advocate
1,418 Views
22 Replies
Message 1 of 23

MAPCAR optimization

Browning_Zed
Advocate
Advocate

Hi All,
I have a need to check if the variables v1 v2 v3 "" are equivalent, and if true, then set these variables to nil. To solve this problem, I created the following code:

 

 

(mapcar
	'set '(v1 v2 v3)
	(mapcar
		'(lambda ( x ) (if (= "" x) (setq x nil) x))
		(list v1 va2 v3)
	)
)

 

 

My question is, is it possible to optimize this code so as not to repeat the list of variables twice? That is, exclude the repetition

'(v1 v2 v3) and (list v1 v2 v3) and define the list of variables once.

0 Likes
Accepted solutions (3)
1,419 Views
22 Replies
Replies (22)
Message 2 of 23

hak_vz
Advisor
Advisor
Accepted solution

No you can not. First list '(v1 v2 v2) is list of variable names, and other is list of values). Check autolisp function QUOTE (short ') and what it does.  Check here quote explanation from @Lee_Mac 

 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 3 of 23

pbejse
Mentor
Mentor
Accepted solution

@Browning_Zed wrote:

Hi All,
I have a need to check if the variables v1 v2 v3 "" are equivalent, and if true, then set these variables to nil. To solve this problem,


As per your code

 

(Setq v1 "Cake" Va2 "" v3 "")
(mapcar '(lambda ( x )
	   (set x (if (/= "" (eval x))(eval x) nil  )))
		'(v1 va2 v3)
	)
--------------------------------------
Result is
("Cake" nil nil) 
_$ v1
"Cake"
_$ va2
nil
_$ v3
nil

 

If you are not planning to use the resulting list from mapcar function, this will be enough

 

(foreach itm '(v1 va2 v3)
  (if (eq "" (eval itm))
    (set itm nil)
  )
)

 

Or are you saying if any of the variables is ""  then set all to nil?

Message 4 of 23

Browning_Zed
Advocate
Advocate

You understood me correctly, I needed to check each variable separately.

But I'm also interested in the option if any of the variables is equivalent to "" then return nil. How can this be done?

0 Likes
Message 5 of 23

hak_vz
Advisor
Advisor
(if (= (apply '+ (mapcar 'strlen (list v1 v2 v3))) 0) (mapcar 'set '(v1 v2 v3) '(nil nil nil)))

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 6 of 23

Browning_Zed
Advocate
Advocate

Thanks. But in this case, you have to repeat the list again. Is it possible to do the same without repeating the list of variables? Perhaps the FOREACH function?

0 Likes
Message 7 of 23

hak_vz
Advisor
Advisor

You need to check equivalency of v1 v2 v3, this is first list appearance. In second part if condition is true we assign values to all variables to nil. It's then completely irrelevant how you do it, either with foreach or mapcar. Those two functions are practically  similar.

You can read this

 

 

(if (= (apply '+ (mapcar 'strlen (list v1 v2 v3))) 0) (mapcar 'set '(v1 v2 v3) '(nil nil nil)))

 

as

 

(if (= (apply '+ (mapcar 'strlen (list "" "" ""))) 0) (mapcar 'set '(v1 v2 v3) '(nil nil nil)))

 

Or with foreach

(if (= (apply '+ (mapcar 'strlen (list v1 v2 v3))) 0) (foreach e '(v1 v2 v3) (set e nil)))

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 8 of 23

pbejse
Mentor
Mentor

@Browning_Zed wrote:

But I'm also interested in the option if any of the variables is equivalent to "" then return nil. How can this be done?


There's a couple of ways to do that. [ you only "see" the list of variables once ]

 

((lambda (l)
   (if (vl-some '(lambda (x) (= (eval x) "" )) l)
     (foreach itm l (set itm nil)))
 )
  '(v1 va2 v3)
)

 

If you want to see a result, you can add (mapcar 'eval l) as else in the if condition.

 

Either way, you need to define the list of variable names  

  • as an argument for mapcar/vl-some/vl-every/foreach....
  • as the invidual names to be assigned a value

 

Message 9 of 23

Browning_Zed
Advocate
Advocate

Thanks pbejse. This option is the most suitable for me. But what do you think about the VL-EVERY function? Is it possible to do optimization using this function? Like this:

(vl-every '/= '("" "") (list v1 v2))

but is there a way to get rid of the '("" "")
?

0 Likes
Message 10 of 23

pbejse
Mentor
Mentor

@hak_vz wrote:
(if (= (apply '+ (mapcar 'strlen (list "" "" ""))) 0) (mapcar 'set '(v1 v2 v3) '(nil nil nil)))

I believe the condition were if "any" of the variable. I could be wrong but what you had applies to  if ALL variable is equivalent to "" then set to nil.

 

0 Likes
Message 11 of 23

pbejse
Mentor
Mentor

@Browning_Zed wrote:

But what do you think about the VL-EVERY function? Is it possible to do optimization using this function? Like this:

(vl-every '/= '("" "") (list v1 v2))


That is the reason why i ask earlier for the condition, Vl-every means "ALL" while vl-some "if any" 

To answer you're question It actually depend on the variable type you are testing,

If you dont want to define a predicate function (lambda) you can do it this way

 

(Setq v1 "d" V2 "" v3 ""

(vl-every 'snvalid (list v1 v2 v3)) --> nil because v2 and v3 is invalid value

(Setq v1 "d" V2 "e" v3 "f")

(vl-every 'snvalid (list v1 v2 v3)) --> T because all three are valid

 

HTH

 

Message 12 of 23

hak_vz
Advisor
Advisor

@pbejse 

@Browning_ZedStated "I have a need to check if the variables v1 v2 v3 "" are equivalent"

 

But if any of condition "any" apply then your solution works.

Or in my version without using vl functions

 

(if (member 0 (mapcar 'strlen (list v1 v2 v3))) (mapcar 'set '(v1 v2 v3) '(nil nil nil)))

 

 

There are so many options to write it.

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 13 of 23

Browning_Zed
Advocate
Advocate

, thank's man. This is what I need, you are cool.👍

0 Likes
Message 14 of 23

pbejse
Mentor
Mentor

@hak_vz wrote:

"I have a need to check if the variables v1 v2 v3 "" are equivalent"


All is well now, It all became so clear at post # 9

 

Cheers

 

0 Likes
Message 15 of 23

Browning_Zed
Advocate
Advocate

OOPS. As it turned out, SNVALID checks other characters and if the value is also equivalent to "=" or "*", or "|" this returns nil as well. It doesn't suit me.

0 Likes
Message 16 of 23

pbejse
Mentor
Mentor
Accepted solution

@Browning_Zed wrote:

...also equivalent to "=" or "*", or "|"  ... it doesn't suit me.


There you go. now you got it. It all depends on the condition/function.

Then you need to define a function

 

(vl-every '(lambda (x)
		    (/= "" x )) (list v1 v2 v3))

 

 

Message 17 of 23

Browning_Zed
Advocate
Advocate

YEAH! This is it!

0 Likes
Message 18 of 23

john.uhden
Mentor
Mentor

Another way to approach this is to see what's left after removing empty strings...

(defun remove_blank (lst)
  (vl-remove-if '(lambda (x)(= x "")) lst)
)

 

John F. Uhden

Message 19 of 23

ronjonp
Advisor
Advisor

Another maybe:

(mapcar 'set '(v1 v2 v3) '("" "" ""))
(if (apply '= (list "" v1 v2 v3))
  (mapcar 'set '(v1 v2 v3) '(nil nil nil))
)
Message 20 of 23

john.uhden
Mentor
Mentor
Very good!
Ya know most, if not all, the mapcar examples dealt with symbol names, but
mine did not. Nor did mine set any symbols to nil. Maybe I should think
before I write.
Anyway, since there's no knowing how many symbols might be in the list,
foreach might be the simplest approach...
(foreach item lst
(if (= (eval item) "")(set item nil))
)
Of course that still leaves the list as '(v1 v2 v3 vn) if that matters.

John F. Uhden

0 Likes