mpcar and lambda

mpcar and lambda

luizhcastanho
Contributor Contributor
435 Views
6 Replies
Message 1 of 7

mpcar and lambda

luizhcastanho
Contributor
Contributor

I'm a beginner!

I'm multiplying and summing block attributes from a list.

 

somaml 0

60 x 2 = 120

somaml 120

320 x 4 = 1280

somaml 1400

170 x 9 = 1530

somaml = 2930

.

.

n

 

; error: too few arguments

 

(defun c:teste()
(setq somaml 0)  
(setq lst (list "L1 60 2" "L2 320 4" "L3 170 9"))
	(foreach lst
		(setq somaml (+ (mapcar (function (lambda (x y) (* atoi (nth 1 x) atoi (nth 2 y)))) lst) somaml))
	)
(princ somaml)
)

 

0 Likes
Accepted solutions (1)
436 Views
6 Replies
Replies (6)
Message 2 of 7

Kent1Cooper
Consultant
Consultant

The error message is probably from the fact that (foreach) needs an item indicator:

  (foreach item lst ....

and then something in the following code needs to refer to item pulling information from each text string in the list.  I haven't fully analyzed the long line yet, but I notice what looks like (nth 1 x) is trying to pull [for example] the "60" out of "L1 60 2", but (nth) is for pulling an item out of a list, not a substring out of a longer string.

 

EDIT:  A different approach, greatly simplified if you can make your list a list of lists, not a list of text strings, with each sub-list containing a string and two integers:

(setq
  lst '(("L1" 60 2) ("L2" 320 4) ("L3" 170 9))
  somaml (apply '+ (mapcar '(lambda (x) (* (nth 1 x) (nth 2 x))) lst))
)

With your list of text strings, they have to be pulled apart to separate the pieces around the spaces.  There are routines available to do that, but a list formatted more appropriately for the purpose makes it much easier.

Kent Cooper, AIA
0 Likes
Message 3 of 7

komondormrex
Mentor
Mentor
(defun c:teste()
	(setq somaml 0)  
	(foreach string (list "L1 60 2" "L2 320 4" "L3 170 9")
		(setq somaml (+ somaml (apply '* (cdr (read (strcat "(" string ")"))))))
	)
	(princ somaml)
)
0 Likes
Message 4 of 7

marko_ribar
Advisor
Advisor

Someone is quicker ... 🙂

 

(defun c:teste ( / somaml lst xl )
  (setq somaml 0)  
  (setq lst (list "L1 60 2" "L2 320 4" "L3 170 9"))
  (foreach x lst
    (setq xl (read (strcat "(" x ")")))
    (setq somaml (+ somaml (* (cadr xl) (caddr xl))))
  )
  (prompt "\nsomaml : ") (princ somaml)
  (princ)
)

 

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

luizhcastanho
Contributor
Contributor

I think I expressed myself wrong. The lst is a list of attribute list.

 

Something like that:

 

(setq lst (list ("L1" "60" "2") ("L2" "320" "4") ("L3 "170" "9")))

 

The list is generated by selecting all blocks, with their respective attributes:

    (setq int -1 sel (ssget "x" (list (cons 0 "INSERT") (cons 410 "Model"))))
  
    (while (setq int (1+ int) ent (ssname sel int))
      (setq ord nil qty nil itm nil)
      (while
        (/= (cdr (assoc 0 (setq get (entget (setq ent (entnext ent))))))
            "SEQEND"
        )
         (setq tag (cdr (assoc 2 get))
               str (cdr (assoc 1 get))
         )
         (vl-some (function (lambda (j k) (and (= tag j) (set k str))))
                  '("CÔMODO" "QTD" "COMPRIMENTO")
                  '(ord qty itm)
         )
      )
      (and ord
           itm
           qty
           (or (vl-some
                 '(lambda (u)
                    (and (eq (car u) ord)
                         (eq (cadr u) itm)
                         (setq
                           lst (subst (list ord
                                            itm
                                            (vl-princ-to-string
                                              (+ (read qty) (read (caddr u)))
                                            )  
                                      )
                                      u
                                      lst
                               )
                         )
                    )
                  )
                 lst
               )
               (setq lst (cons (list ord itm qty) lst))
           )
      )
      lst
    )  

 

0 Likes
Message 6 of 7

Kent1Cooper
Consultant
Consultant
Accepted solution

@luizhcastanho wrote:

(setq lst (list ("L1" "60" "2") ("L2" "320" "4") ("L3 "170" "9")))


That would need to be:

(setq lst (list '("L1" "60" "2") '("L2" "320" "4") '("L3 "170" "9")))

or:

(setq lst '(("L1" "60" "2") ("L2" "320" "4") ("L3 "170" "9")))

 

Then somaml becomes:

(apply '+ (mapcar '(lambda (x) (* (atoi (nth 1 x)) (atoi (nth 2 x)))) lst))

Kent Cooper, AIA
Message 7 of 7

Sea-Haven
Mentor
Mentor

Agree with you Kent about make list, this is like part 2 of another post and missing information in that post also,

 

The lst can retain the numbers and the alpha. Look at 1st post about 60*2.

 

 

 

(setq lst (list '("L1" 60 2) '("L2" 320 4) '("L3" 170 9)))

or:

(setq lst '(("L1" 60 2) ("L2" 320 4) ("L3" 170 9)))

 

 

I have something that takes block attributes and outputs the answer to a table. Is that your next post ? Please continue in 1 post.

 

Can you post a sample dwg ?