Jump to content

List extraction question


lastknownuser

Recommended Posts

I can't figure out a problem I'm having. I have a list, for example: ((1 (<Entity name: 8290b880>)) (1 (<Entity name: 8290b940>)) (2 (<Entity name: 8290ba00>)))
I would need to extract all elements with the number 1. So new list would need to be ((1 (<Entity name: 8290b880>)) (1 (<Entity name: 8290b940>)))
Basically, I want to delete all non duplicated elements from the list by the first key element. I found a function that does it by the member alanjt, but it works only for lists like '(1 1 2), and here a have a nested list (I think)
Any help would be welcome, I attached the mentioned function code below, maybe it could be adjusted for my needs
 

(defun AT:ListDuplicates (lst)
 ;; Return all duplicates within list
 ;; lst - List to process
 ;; Alan J. Thompson, 11.01.09
 (vl-remove-if-not (function (lambda (x) (member x (cdr (member x lst))))) lst)
)

 

Link to comment
Share on other sites

How are you building the fist list?

 

 ((1 (<Entity name: 8290b880>)) (1 (<Entity name: 8290b940>)) (2 (<Entity name: 8290ba00>)))

Edited by mhupp
Link to comment
Share on other sites

2 hours ago, mhupp said:

How are you building the fist list?

 

 ((1 (<Entity name: 8290b880>)) (1 (<Entity name: 8290b940>)) (2 (<Entity name: 8290ba00>)))


    (setq element (list pointid (list blockid)))
    (setq lst (cons element lst))

I'm testing blocks in sset and want to find those with the same certain attributes, is there a better way to construct the list?

Link to comment
Share on other sites

This will ask you to input a tag name or you can right click and select a tag.

then it will highlight all blocks with that tag name in it.

 

(defun c:selbytag ( / a e i n s x )
   (setq n (getstring "\nEnter Tag Name: "))
   (if (eq n "")
     (setq n (cdr (assoc 2 (entget (car (nentsel "pick attribute"))))))
   )
   (if (setq s (ssget "_X" '((0 . "INSERT") (66 . 1))))
       (repeat (setq i (sslength s))
           (setq i (1- i)
                 e (ssname  s i)
                 a (entnext e)
                 x (entget  a)
           )
           (while (and (= "ATTRIB" (cdr (assoc 0 x))) (/= n (strcase (cdr (assoc 2 x)))))
               (setq a (entnext a)
                     x (entget  a)
               )
           )
           (or (= "ATTRIB" (cdr (assoc 0 x))) (ssdel e s))  ;removes blocks that don't have the tag name
       )
   )
   (sssetfirst nil s) (princ)
)

 

The tag name not the value.

tag.png.2710ae3839343a2b97f7a599f2d91f4e.png

 

Source

Edited by mhupp
Link to comment
Share on other sites

@mhupp thanks for the effort but I really need it in the form of a list. And also, I'm trying to filter my data by the value of the certain tag, so in my previous post, the "pointid" would be tag value, and "blockid" is the block containing that value.

Link to comment
Share on other sites

I'm lacking in list manipulation. this should work.

 

(defun getmatches ( p l )
  (vl-remove-if-not '(lambda ( x ) (vl-some '(lambda ( y ) (wcmatch y p)) x)) l)
)

(getmatches element lst)

 

 

Edited by mhupp
Link to comment
Share on other sites

(defun foo (lst / l n)
    (setq n (length lst) l (mapcar 'car lst))
    (vl-remove-if '(lambda (a) (= (- n (length (vl-remove (car a) l))) 1)) lst)
)

 

  • Like 2
Link to comment
Share on other sites

8 minutes ago, Jonathan Handojo said:

(defun foo (lst / l n)
    (setq n (length lst) l (mapcar 'car lst))
    (vl-remove-if '(lambda (a) (= (- n (length (vl-remove (car a) l))) 1)) lst)
)

 


Thank you! 

Link to comment
Share on other sites

31 minutes ago, mhupp said:

lol not even close! @Jonathan Handojo you mind breaking down what you posted.  everything past lambda

 

First, we get the length of the list as a whole, i.e. the number of items in that list (stored in variable n). Then we remove every occurrence of that element from the list using vl-remove and take its length, which is (length (vl-remove (car a) l)). Subtracting the total length with the removed length gives you the number of occurrences of that item in the list, so if it's not equal to 1 (or greater than 1), remove that item from the list.

 

So:

 

l is stored as (1 1 2) and n as 3. Let's take the last item of the list, a=(2 (<Entity name: 8290ba00>))

 

(car a) = 2

(vl-remove 2 l) = (1 1)

(length (1 1)) = 2

(- n 2) --> (- 3 2) = 1

(= 1 1) = T, therefore remove item from list.

 

So if a=(1 (<Entity name: 8290b880>)):

 

(car a) = 1

(vl-remove 1 l) = (2)

(length (2)) = 1

(- n 1) --> (- 3 1) = 2

(= 2 1) = nil, therefore do not remove item from list.

 

By the way, debugging is something that programmers must be able to perform. You can use it in this case too even thought it doesn't yield any errors. But I have to say, that it does yield an error when I first write it up and tested it. No matter how skilled anyone is at programming (myself, Lee, and all the best programmers out there), you're bound to make a mistake at some point, especially codes with thousands of lines, so it's good to know where they occur in order to be able to fix the error. To do that, we use the debugging feature of AutoLISP. These can include step-by-step execution and variable watching. Lee Mac has provided an excellent tutorial in this link and it is VERY important for programmers to be able to use this. You can also use it in this scenario to see how the code functions.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Thank you for the explanation Jonathan Handojo. Being self taught I think I learned how to debug before coding to figure out why stuff i was writing wasn't working lol.  Its just some areas of lisp I don't use very often so its greek to me and why i like to come here daily. Been spending the last few hours reading over list manipulation. I think using car on the sublist themselves you don't have to do all that math. please check my work.

 

(setq mylist '((1 (<Entity name: 800>)) (1 (<Entity name: 801>)) (2 (<Entity name: 802>)) (2 (<Entity name: 803>)) (1 (<Entity name: 804>)) (1 (<Entity name: 805>)) (4 (<Entity name: 806>)) (3 (<Entity name: 807>))))
  
(defun foo (lst ele)
  (vl-remove-if-not '(lambda ( x ) (= (car x) ele)) lst)
)
  
(foo mylist 1)
((1 (<ENTITY NAME: 800>)) (1 (<ENTITY NAME: 801>)) (1 (<ENTITY NAME: 804>)) (1 (<ENTITY NAME: 805>)))
(foo mylist 2)
((2 (<ENTITY NAME: 802>)) (2 (<ENTITY NAME: 803>)))

 

 

Edited by mhupp
Link to comment
Share on other sites

Just now, mhupp said:

Thank you for the explanation Jonathan Handojo. Being self taught I think I learned how to debug before coding.  Its just some areas of lisp I don't use very often so its greek to me. Been spending the last few hours reading over list manipulation. I think using car on the sublist themselves you don't have to do all that math. please check my work.

 


(setq mylist '((1 (<Entity name: 800>)) (1 (<Entity name: 801>)) (2 (<Entity name: 802>)) (2 (<Entity name: 803>)) (1 (<Entity name: 804>)) (1 (<Entity name: 805>)) (4 (<Entity name: 806>)) (3 (<Entity name: 807>))))
  
(defun foo (lst ele)
  (vl-remove-if-not '(lambda ( x ) (= (car x) ele)) lst)
)
  
(foo mylist 1)
((1 (<ENTITY NAME: 800>)) (1 (<ENTITY NAME: 801>)) (1 (<ENTITY NAME: 804>)) (1 (<ENTITY NAME: 805>)))
(foo mylist 2)
((2 (<ENTITY NAME: 802>)) (2 (<ENTITY NAME: 803>)))

 

 

 

If you are talking about getting all elements in the list whose first element in each sublist matches the supplied second argument, I'll give you an A+ and I would also go the same approach you've taken. My personal preference, I would use equal instead of = to account for any tolerances just in case AutoLISP gets glitchy (it won't happen with INT, but just in case, I can get really pedantic). I suppose the original post was requesting for both the removal of duplicates and extracting by value. I only assumed that he wanted to delete the non-duplicates since that seemed to hold the criterion, so I wrote that function.

  • Like 1
  • Thanks 1
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...