Retrieving elements from a "list of lists"

Retrieving elements from a "list of lists"

dmfrazier
Advisor Advisor
3,249 Views
8 Replies
Message 1 of 9

Retrieving elements from a "list of lists"

dmfrazier
Advisor
Advisor

Let's say I have set the following (simplified) "list of lists" to a variable ("ItemList"):

 

( ("DWG_01" , "DESC_01" , "PART_01")
  ("DWG_02" , "DESC_02" , "PART_02")
  ("DWG_03" , "DESC_03" , "PART_03")
)

 

Now, I want to "get" from one of the lists in this group of lists the 2nd and 3rd "pieces" based on the 1st piece.

 

For example, I have determined that a certain (selected) block insert in the DWG contains a certain attribute and its value is set to "DWG_01". I want to retrieve (individually) the 2nd and 3rd elements of the list which has the 1st element = "DWG_01" and then store each of those (individually). How do I go about retrieving these elements from the list (of lists)?

 

Any help would be greatly appreciated..

0 Likes
Accepted solutions (2)
3,250 Views
8 Replies
Replies (8)
Message 2 of 9

Ranjit_Singh
Advisor
Advisor

Assuming each of the first items in the lists has no other duplicates, following should give you what you want. However, if there are duplicates then some more information is needed to determine the logic

(setq itemlist '(("DWG_01" , "DESC_01" , "PART_01")  ("DWG_02" , "DESC_02" , "PART_02")  ("DWG_03" , "DESC_03" , "PART_03")))
(foreach i itemlist (if (= (car i) "DWG_01") (progn (setq var1 (nth 2 i) var2 (last i)))))
0 Likes
Message 3 of 9

Kent1Cooper
Consultant
Consultant
Accepted solution

The 'itemlist' should not have commas between entries.  They are not part of the standard way of building a list, and they "count" as items in the list, and make things more complicated than they need to be. Try it without them:

(setq itemlist '(("DWG_01" "DESC_01" "PART_01")  ("DWG_02" "DESC_02" "PART_02")  ("DWG_03" "DESC_03" "PART_03")))

 

That is an association list [actually, with or without the commas], and you can get the parts related to the first entry easily.  Presumably you put that value you've determined into a variable:

 

(setq attval "DWG_01")

 

Then there's no need to step through the list of lists, checking whether the first item in each matches that value, but you can go straight to the one you want:

 

Command: (assoc attval itemlist)

returns
("DWG_01" "DESC_01" "PART_01")

 

You can get the second and third ones in one list, if that's of any use to you, just as entity data is often extracted:

(setq 2nd3rd (cdr (assoc attval itemlist)))

returns

("DESC_01" "PART_01")

from which you can pull out the pieces separately, either to put into variables or just to use without variables.

 

Or, you can set them into their own separate variables directly, without the middle-man:

(setq

  2nd (cadr (assoc attval itemlist))

  3rd (caddr (assoc attval itemlist))

)

 

This could all be done with the commas in there, using different (ca....) functions, or (nth), but I don't see any reason for doing so.

Kent Cooper, AIA
Message 4 of 9

dmfrazier
Advisor
Advisor

Thank you, Kent, for the heads-up on the commas - a careless mistake when I produced the lists.

 

I had a sense that it would be relatively simple.  Thank you.  Your instructions were very helpful.

 

Now this has uncovered another issue: I'm modifying (replacing) the values of two attributes in the selected block insert.  One of the attributes changes correctly, but the other doesn't change at all, and there's no error message.  I suspect that it is due to the fact that this particular attribute is multi-line.

 

To change the attributes I'm using the following (sub)function:

 

;;; Function to update one or more block attribute value(s) in a block insert.
;;; Insert can be identified by it's Entity ID or name.
;;; Passed: <Block Ename or Block name> <List of the type: ((Attribute Name . New Value)(... ))>

(defun UpdBlk (BlkEN AttLst / OrgEN SS E ITM TagIdx AttNam AttVal TAG FndLst)
 (setq TagIdx nil)
 (setq OrgEN  BlkEN)
 (setq FndLst '("FN" "BOM_CCN" "BOM_STRID" "BOM_STRREV"))
 (if (= (type BlkEN) 'STR)
  (if (setq SS (ssget "X" (list (cons 0 "INSERT") (cons 2 BlkEN))))
   (setq BlkEN (ssname SS 0))
   (setq BlkEN nil)
  )
 )
 (foreach ITM AttLst
  (setq TagIdx (append TagIdx (list (car ITM))))
 )
 (if BlkEN
  (progn
   (setq E (entget (entnext BlkEN)))
   (while (= (cdr (assoc 0 E)) "ATTRIB")
    (setq TAG (cdr (assoc 2 E)))
    (if (member TAG TagIdx)
     (progn
      (setq VAL (cdr (assoc TAG AttLst)))
      (if (not VAL)
       (setq VAL "??")
      )
      (if (= (strcase VAL) "**ERROR**")
       (setq VAL "")
      )
      (setq E      (subst (cons 1 VAL) (assoc 1 E) E)
            FndLst (append FndLst (list TAG))
      )
      (entmod E)
     )
    )
    (setq E (entget (entnext (cdr (assoc -1 E)))))
   )
   (entupd BlkEN)
   (foreach ITM AttLst
    (setq ITM (car ITM))
    (if (not (member ITM FndLst))
     (if ITM
      (princ (strcat "\nError, No attribute named '"
                     ITM
                     "' exists in block "
                     (cdr (assoc 2 (entget BlkEN)))
                     " !"
             )
      )
      (princ
       "\nError, Invalid Attribute 'TAG' name passed to Block Attribute update function!"
      )
     )
    )
   )
  );progn
  (if (= (type OrgEN) 'STR)
   (alert (strcat "Error! Invalid Block Name ["
                  OrgEN
                  "] passed to block update!"
          )
   )
   (progn
    (princ "\nPassed entity name was  [")
    (princ OrgEN)
    (princ "]   ")
    (alert
     "Error! Invalid Block Entity Name was passed to block update!
           \nInvalid entry's name is on command printed below."
    )
   ) ;progn
  ) ;if
 ) ;if
) ;defun

 

(Note: some pieces of this function appear to be "remnants" from its original purpose, which could probably be removed, but so far they haven't caused me any problems.)

 

Again, any clues would be greatly appreciated.

0 Likes
Message 5 of 9

hmsilva
Mentor
Mentor

@dmfrazier wrote:

...

Now this has uncovered another issue: I'm modifying (replacing) the values of two attributes in the selected block insert.  One of the attributes changes correctly, but the other doesn't change at all, and there's no error message.  I suspect that it is due to the fact that this particular attribute is multi-line.

 

To change the attributes I'm using the following (sub)function:

 ...


Hi dmfrazier,

MText in ATTRIBs have two 'assoc 1', the first, the default value "" and the second, after (101 . "Embedded Object")' is the string.

 

Try to change (untested)

 

(setq E      (subst (cons 1 VAL) (assoc 1 E) E)
      FndLst (append FndLst (list TAG))
)

to

 

(if (setq memb (member '(101 . "Embedded Object") E))
   (setq E    (subst (cons 1 VAL) (assoc 1 memb) E)
         FndLst (append FndLst (list TAG))
   )
   (setq E    (subst (cons 1 VAL) (assoc 1 E) E)
         FndLst (append FndLst (list TAG))
   )
)

But I would suggest to use ActveX method because if the MText string is too long, It will be divided by multiple 'assoc 3' 250-character long...

 

 

Hope this helps,
Henrique

EESignature

0 Likes
Message 6 of 9

dmfrazier
Advisor
Advisor

Thanks, Henrique.

No, that doesn't work - now it doesn't change either type of attribute.

 

I did some research and had learned what you have said about the second "assoc 1".  I think I might need to produce a second version of the function specifically for multi-line attributes.  I will work on that tomorrow.

 

Oh, P.S., the longer-than-250-character issue will not apply in my case.

0 Likes
Message 7 of 9

hmsilva
Mentor
Mentor
Accepted solution

@dmfrazier wrote:

Thanks, Henrique.

No, that doesn't work - now it doesn't change either type of attribute.

 

I did some research and had learned what you have said about the second "assoc 1".  I think I might need to produce a second version of the function specifically for multi-line attributes.  I will work on that tomorrow.

 

Oh, P.S., the longer-than-250-character issue will not apply in my case.


Did you test the mod with the edited code?

I had a typo in my original post...

 

;;; Function to update one or more block attribute value(s) in a block insert.
;;; Insert can be identified by it's Entity ID or name.
;;; Passed: <Block Ename or Block name> <List of the type: ((Attribute Name . New Value)(... ))>

(defun UpdBlk (BlkEN AttLst / OrgEN SS E ITM TagIdx AttNam AttVal TAG FndLst memb)
   (setq TagIdx nil)
   (setq OrgEN BlkEN)
   (setq FndLst '("FN" "BOM_CCN" "BOM_STRID" "BOM_STRREV"))
   (if (= (type BlkEN) 'STR)
      (if (setq SS (ssget "X" (list (cons 0 "INSERT") (cons 2 BlkEN))))
         (setq BlkEN (ssname SS 0))
         (setq BlkEN nil)
      )
   )
   (foreach ITM AttLst
      (setq TagIdx (append TagIdx (list (car ITM))))
   )
   (if BlkEN
      (progn
         (setq E (entget (entnext BlkEN)))
         (while (= (cdr (assoc 0 E)) "ATTRIB")
            (setq TAG (cdr (assoc 2 E)))
            (if (member TAG TagIdx)
               (progn
                  (setq VAL (cdr (assoc TAG AttLst)))
                  (if (not VAL)
                     (setq VAL "??")
                  )
                  (if (= (strcase VAL) "**ERROR**")
                     (setq VAL "")
                  )
                  (if (setq memb (member '(101 . "Embedded Object") E))
                     (setq E      (subst (cons 1 VAL) (assoc 1 memb) E)
                           FndLst (append FndLst (list TAG))
                     )
                     (setq E      (subst (cons 1 VAL) (assoc 1 E) E)
                           FndLst (append FndLst (list TAG))
                     )
                  )
                  (entmod E)
               )
            )
            (setq E (entget (entnext (cdr (assoc -1 E)))))
         )
         (entupd BlkEN)
         (foreach ITM AttLst
            (setq ITM (car ITM))
            (if (not (member ITM FndLst))
               (if ITM
                  (princ (strcat "\nError, No attribute named '"
                                 ITM
                                 "' exists in block "
                                 (cdr (assoc 2 (entget BlkEN)))
                                 " !"
                         )
                  )
                  (princ
                     "\nError, Invalid Attribute 'TAG' name passed to Block Attribute update function!"
                  )
               )
            )
         )
      ) ;progn
      (if (= (type OrgEN) 'STR)
         (alert (strcat "Error! Invalid Block Name ["
                        OrgEN
                        "] passed to block update!"
                )
         )
         (progn
            (princ "\nPassed entity name was  [")
            (princ OrgEN)
            (princ "]   ")
            (alert
               "Error! Invalid Block Entity Name was passed to block update!
           \nInvalid entry's name is on command printed below."
            )
         ) ;progn
      ) ;if
   ) ;if
) ;defun

 

 

Henrique

EESignature

Message 8 of 9

dmfrazier
Advisor
Advisor

I didn't realize you had edited your post, so, no, I had not tried the latest code.

 

I just used it and it works!  Fantastic!

 

Thank you so much, Henrique!

0 Likes
Message 9 of 9

hmsilva
Mentor
Mentor

@dmfrazier wrote:

I didn't realize you had edited your post, so, no, I had not tried the latest code.

 

I just used it and it works!  Fantastic!

 

Thank you so much, Henrique!


You're welcome, dmfrazier
Glad I could help!

Henrique

EESignature

0 Likes