Author Topic: vl-member-if / vl-member-if-not  (Read 3139 times)

0 Members and 1 Guest are viewing this topic.

QuestionEverything

  • Guest
vl-member-if / vl-member-if-not
« on: September 28, 2016, 04:24:04 AM »
Hi, Its me again with another question:
What are used for vl-member-if / vl-member-if-not ?
I understand the usage of: vl-remove / vl-remove-if / vl-remove-if-not. But can you post any practical examples of vl-member-*** usage?

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: vl-member-if / vl-member-if-not
« Reply #1 on: September 28, 2016, 05:11:35 AM »
You should try to search for examples first. Enough can be found.
Code: [Select]
(vl-member-if 'numberp '("a" "b" 1 "c" "d" 2)) => (1 "c" "d" 2)

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: vl-member-if / vl-member-if-not
« Reply #2 on: September 28, 2016, 05:16:50 AM »
It does something similar to the member function. I.e. it finds the first occurrence of an item in the list, then returns the list from that item onwards.


Only in this case it doesn't search by equality, rather it allows you to give it a predicate function. I.e. the difference between vl-remove and vl-remove-if.


This sort of thing is generally used to find a set of values in a list starting at a specific position. E.g. to find the list to vector points in a LWPolyline means you want to find the first item with a 10 as its first sub-item, and all that follow it. E.g.
Code: [Select]
Command: (entget (entlast))
((-1 . <Entity name: 3d9bea7db0>) (0 . "LWPOLYLINE") (330 . <Entity name: 3da35c59f0>) (5 . "273") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbPolyline") (90 . 3) (70 . 0) (43 . 0.0) (38 . 0.0) (39 . 0.0) (10 2248.02 1657.69) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 3039.1 2029.71) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 3919.75 1712.42) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (210 0.0 0.0 1.0))
I could do this:
Code: [Select]
Command: (setq data (entget (entlast)))
((-1 . <Entity name: 3d9bea7db0>) (0 . "LWPOLYLINE") (330 . <Entity name: 3da35c59f0>) (5 . "273") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbPolyline") (90 . 3) (70 . 0) (43 . 0.0) (38 . 0.0) (39 . 0.0) (10 2248.02 1657.69) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 3039.1 2029.71) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 3919.75 1712.42) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (210 0.0 0.0 1.0))
Command: (member (assoc 10 data) data)
((10 2248.02 1657.69) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 3039.1 2029.71) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 3919.75 1712.42) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (210 0.0 0.0 1.0))
But that means it only works on association lists, and it also searches through the list twice (once to find the association item and second to find the exact match). Rather this may be more efficient:
Code: [Select]
Command: (vl-member-if '(lambda (a) (= (car a) 10)) (entget (entlast)))
((10 2248.02 1657.69) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 3039.1 2029.71) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 3919.75 1712.42) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (210 0.0 0.0 1.0))
Not to mention, I could have searched on multiple criteria. Say I wanted to find the first vector where the x value is greater than 3000:
Code: [Select]
Command: (vl-member-if '(lambda (a) (and (= (car a) 10) (> (cadr a) 3000))) (entget (entlast)))
((10 3039.1 2029.71) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 3919.75 1712.42) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (210 0.0 0.0 1.0))
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

QuestionEverything

  • Guest
Re: vl-member-if / vl-member-if-not
« Reply #3 on: September 28, 2016, 03:10:05 PM »
Thank you, irneb! Exact type of ''usage examples'' what I needed, I will post again if I have further questions about it.
It looks like some enchanced assoc for lists, like (apply 'assoc list).
« Last Edit: September 28, 2016, 03:14:50 PM by QuestionEverything »

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: vl-member-if / vl-member-if-not
« Reply #4 on: September 29, 2016, 11:18:22 AM »
Thank you, irneb! Exact type of ''usage examples'' what I needed, I will post again if I have further questions about it.
You're welcome
It looks like some enchanced assoc for lists, like (apply 'assoc list).
Not exactly. The problem is assoc only extracts one item when its start equals a certain value.

Similar goes for member. It searches for the first item equal to some value, then returns that item including the rest of the list.

vl-member-if does something similar to member. It's just that it doesn't compare on equality. Rather it allows you to create a custom predicate function instead - so you can compare on anything you wish.


If you wanted that idea but getting a single value (like with assoc) you could use vl-member-if with a car wrapped around it. Something like this:
Code - Auto/Visual Lisp: [Select]
  1. (defun assoc-if (predicate association-list)
  2.   (car (vl-member-if
  3.          '(lambda (item) (apply predicate (list (car item))))
  4.          association-list
  5.        )
  6.   )
  7. )
Notice the differences:
Code: [Select]
_$ (setq test-list '((1 . 3) (3 . 5) (2 . 4) (8 . 2) (6 . 5)))
((1 . 3) (3 . 5) (2 . 4) (8 . 2) (6 . 5))
_$ (assoc-if '(lambda (item) (> item 3)) test-list)
(8 . 2)
_$ (vl-member-if '(lambda (item) (> (car item) 3)) test-list)
((8 . 2) (6 . 5))
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.