Marcin O Posted March 25 Posted March 25 (edited) Hello, I would like to ask if someone tried to create in AutoLISP similar function to lookup in Excel. Arguments of the functions are: - list of lists - string or number to search in the first column - column number to return the result of corresponding row My code looks like that but i belive there might be a better solutions (defun C:lookup (lst search-val column-index / result) (setq result nil) (foreach row lst (if (= (car row) search-val) (setq result (nth (1- column-index) row)) ) ) (if result result nil ) ) my example list of list looks like: ((10 26509533.29 26509533.29 100.0) (11 26509533.29 26509533.29 100.0) (20 9985631.7 9985631.7 100.0) (21 9985631.7 9985631.7 100.0) (30 6266660.57 6266660.57 20.0) (31 3521388.16 3521388.16 30.0)) Best greetings Marcin Edited March 25 by Marcin O post code and example so it's more clear for readers Quote
Saxlle Posted March 26 Posted March 26 (edited) Hi @Marcin O, I didn't search it on google, but you can try with something like this: ; ********************************************************************** ; Functions : test (temporary defined) ; Subfunctions : LM:str->lst ; Description : Searching for the desired pattern in the list ; Author : SAXLLE ; Date : March 26, 2025 ; ********************************************************************** (prompt "\nTo run a LISP type: test") (princ) (defun c:test ( / example_list search_value len i example_list_concat val1 val2 val3 val4 val5 output_list_length row output example_list_concat_separate col) (setq example_list '((10 26509533.29 26509533.29 100.0) (11 26509533.29 26509533.29 100.0) (12 "CADTutor" 26509533.29 100.0) (20 9985631.7 9985631.7 100.0 "AutoLISP") (21 9985631.7 9985631.7 100.0) (30 6266660.57 "Topic" 20.0) (31 3521388.16 3521388.16 30.0) (32 3521388.16 3521388.16 30.0 "Programming"))) (princ (vl-princ-to-string example_list)) (princ) (setq search_value (getstring "\nInput the Number or String as search pattern: ")) ;; Check if the pattern for search is INTEGER, REAL or STRING value (cond ((and (equal (type (atoi search_value)) 'INT) (not (equal (atoi search_value) 0))) (setq search_value (atoi search_value)) ;; The search pattern is INTEGER value and it's converted into INT ) ((and (equal (type (atoi search_value)) 'REAL) (not (equal (atoi search_value) 0))) (setq search_value (distof search_value 2)) ;; The search pattern is REAL value and it's converted into REAL ) (t (setq search_value search_value) ;; The search pattern is STRING value and it's keep that type ) ) ;; Initialize length of the list and iterators "i" (setq len (length example_list) i 0 example_list_concat nil ) ;; Iterate through the list to find matching value from search pattern from variable "search_value" (while (< i len) ;; Finding matching index value with "search value" (if (member search_value (nth i example_list)) ;; start progn (progn ;; Main cond (cond ;; If the length of the "example_list" is 2 elements ((equal (length (nth i example_list)) 2) ;; Adding to every variable value from list (mapcar 'set '(val1 val2) (nth i example_list)) ;; Check if val1 equal to INT or REAL or STR (if (equal (type val1) 'INT) (setq val1 (itoa val1)) (if (equal (type val1) 'REAL) (setq val1 (rtos val1 2 2)) (if (equal (type val1) 'STR) (setq val1 val1) ) ) ) ;; Check if val2 equal to INT or REAL or STR (if (equal (type val2) 'INT) (setq val2 (itoa val2)) (if (equal (type val2) 'REAL) (setq val2 (rtos val2 2 2)) (if (equal (type val2) 'STR) (setq val2 val2) ) ) ) ;; Find the in which row is the "search_value" (setq row (1+ i)) ;; Create the list of values (setq example_list_concat (strcat val1 "/" val2)) ;; Get the length of elements from the "example_list_concat" list (setq output_list_length 2) ) ;; end cond with 2 elements ;; If the length of the "example_list" is 3 elements ((equal (length (nth i example_list)) 3) ;; Adding to every variable value from list (mapcar 'set '(val1 val2 val3) (nth i example_list)) ;; Check if val1 equal to INT or REAL or STR (if (equal (type val1) 'INT) (setq val1 (itoa val1)) (if (equal (type val1) 'REAL) (setq val1 (rtos val1 2 2)) (if (equal (type val1) 'STR) (setq val1 val1) ) ) ) ;; Check if val2 equal to INT or REAL or STR (if (equal (type val2) 'INT) (setq val2 (itoa val2)) (if (equal (type val2) 'REAL) (setq val2 (rtos val2 2 2)) (if (equal (type val2) 'STR) (setq val2 val2) ) ) ) ;; Check if val3 equal to INT or REAL or STR (if (equal (type val3) 'INT) (setq val3 (itoa val3)) (if (equal (type val3) 'REAL) (setq val3 (rtos val3 2 2)) (if (equal (type val3) 'STR) (setq val3 val3) ) ) ) ;; Find the in which row is the "search_value" (setq row (1+ i)) ;; Create the list of values (setq example_list_concat (strcat val1 "/" val2 "/" val3)) ;; Get the length of elements from the "example_list_concat" list (setq output_list_length 3) ) ;; end cond with 3 elements ;; If the length of the "example_list" is 4 elements ((equal (length (nth i example_list)) 4) ;; Adding to every variable value from list (mapcar 'set '(val1 val2 val3 val4) (nth i example_list)) ;; Check if val1 equal to INT or REAL or STR (if (equal (type val1) 'INT) (setq val1 (itoa val1)) (if (equal (type val1) 'REAL) (setq val1 (rtos val1 2 2)) (if (equal (type val1) 'STR) (setq val1 val1) ) ) ) ;; Check if val2 equal to INT or REAL or STR (if (equal (type val2) 'INT) (setq val2 (itoa val2)) (if (equal (type val2) 'REAL) (setq val2 (rtos val2 2 2)) (if (equal (type val2) 'STR) (setq val2 val2) ) ) ) ;; Check if val3 equal to INT or REAL or STR (if (equal (type val3) 'INT) (setq val3 (itoa val3)) (if (equal (type val3) 'REAL) (setq val3 (rtos val3 2 2)) (if (equal (type val3) 'STR) (setq val3 val3) ) ) ) ;; Check if val4 equal to INT or REAL or STR (if (equal (type val4) 'INT) (setq val4 (itoa val4)) (if (equal (type val4) 'REAL) (setq val4 (rtos val4 2 2)) (if (equal (type val4) 'STR) (setq val4 val4) ) ) ) ;; Find the in which row is the "search_value" (setq row (1+ i)) ;; Create the list of values (setq example_list_concat (strcat val1 "/" val2 "/" val3 "/" val4)) ;; Get the length of elements from the "example_list_concat" list (setq output_list_length 4) ) ;; end cond with 4 elements ;; If the length of the "example_list" is 5 elements ((equal (length (nth i example_list)) 5) ;; Adding to every variable value from list (mapcar 'set '(val1 val2 val3 val4 val5) (nth i example_list)) ;; Check if val1 equal to INT or REAL or STR (if (equal (type val1) 'INT) (setq val1 (itoa val1)) (if (equal (type val1) 'REAL) (setq val1 (rtos val1 2 2)) (if (equal (type val1) 'STR) (setq val1 val1) ) ) ) ;; Check if val2 equal to INT or REAL or STR (if (equal (type val2) 'INT) (setq val2 (itoa val2)) (if (equal (type val2) 'REAL) (setq val2 (rtos val2 2 2)) (if (equal (type val2) 'STR) (setq val2 val2) ) ) ) ;; Check if val3 equal to INT or REAL or STR (if (equal (type val3) 'INT) (setq val3 (itoa val3)) (if (equal (type val3) 'REAL) (setq val3 (rtos val3 2 2)) (if (equal (type val3) 'STR) (setq val3 val3) ) ) ) ;; Check if val4 equal to INT or REAL or STR (if (equal (type val4) 'INT) (setq val4 (itoa val4)) (if (equal (type val4) 'REAL) (setq val4 (rtos val4 2 2)) (if (equal (type val4) 'STR) (setq val4 val4) ) ) ) ;; Check if val5 equal to INT or REAL or STR (if (equal (type val5) 'INT) (setq val5 (itoa val5)) (if (equal (type val5) 'REAL) (setq val5 (rtos val5 2 2)) (if (equal (type val5) 'STR) (setq val5 val5) ) ) ) ;; Find the in which row is the "search_value" (setq row (1+ i)) ;; Create the list of values (setq example_list_concat (strcat val1 "/" val2 "/" val3 "/" val4 "/" val5)) ;; Get the length of elements from the "example_list_concat" list (setq output_list_length 5) ) ;; end cond with 5 elements ) ;; end Main cond ) ;; end progn ) ;; end if (setq i (1+ i)) ;; Adding "1+" to iterator "i" to take next element from the list ) ;; end while ;; start if (if (/= example_list_concat nil) ;; 1. progn (progn (initget 1 (vl-string-translate "/" " " example_list_concat)) ;; Pick the desired output value for further iteration (setq output (getkword (strcat "\nChoose a value from the list [" example_list_concat "]: "))) (prompt (strcat "\nThe output value is: " output)) (princ) ;; Convert "example_list_concat" into the list of separate values (setq example_list_concat_separate (LM:str->lst example_list_concat "/")) ;; Find the in which column is the "output" value (setq col (itoa (+ (vl-position output example_list_concat_separate) 1))) ;; Find the in which column is the "output" value (prompt (strcat "\nThe output value is at row: " (itoa row) " and the column is: " col)) (princ) ) ;; end 1. progn ;; 2. progn (progn (prompt "\nThe searched value doesn't exist in the list.") (princ) ) ;; end 2. progn ) ;; end if ) ;; String to List - Lee Mac ;; Separates a string using a given delimiter ;; str - [str] String to process ;; del - [str] Delimiter by which to separate the string ;; Returns: [lst] List of strings (defun LM:str->lst ( str del / pos ) (if (setq pos (vl-string-search del str)) (cons (substr str 1 pos) (LM:str->lst (substr str (+ pos 1 (strlen del))) del)) (list str) ) ) As you can see in the "example_list", there is a values which are type INT, REAL or STRING. Based on the input value which are stored in variable "search_value", it will be converted into to desired value type. Inside the "while loop", if the "search_value" is the member one of the element in the "example_list" it will return that element from the "example_list". The next is to check the length of that returned elements from list (how many elements contain that element from list). Based on the length, the number of "variables" will be equal to the length. Every variable will store the value, and when the "while loop" end and if variable "example_list_concat" isn't nil/empty, it will ask you to choose the desired value choosing by mouse or arrows (up and down) by hiting the ENTER. On that way, you can get desired value from "example_list". At the end, you will get a row and column for searched value. I think that is the best way to use in LISP which are going to be similar as excel function "LOOKUP". Try to paste that example which I posted it in AutoCAD and try to play with it. Notice: The max length of variables which can be stored in the "example list concat" is 5, and the length can be modified as many as you want (6, 7, 8, etc., need to modify the code). Best regards. Edited March 26 by Saxlle Add printing the values from the list in command-line. Update the code to return the row and column. Quote
Saxlle Posted March 26 Posted March 26 (edited) Here is the an example video where you can see how it works. Search pattern into the list.mp4Fetching info... Edited March 26 by Saxlle Uploaded the second video according to the number of row and column of searched value. Quote
Steven P Posted April 7 Posted April 7 If the reference in the list is a number, as in the example, 10, 11, 20, 21... then you can use it like an associated list, return the sub list fairly easily: This will grab '20' - change to suit. You can ignore the '20' value in the return with (cdr..... (setq MyList (list '(10 26509533.29 26509533.29 100.0) '(11 26509533.29 26509533.29 100.0) '(20 9985631.7 9985631.7 100.0) '(21 9985631.7 9985631.7 100.0) '(30 6266660.57 6266660.57 20.0) '(31 3521388.16 3521388.16 30.0) ) ; end list ) ; end setq (setq Return (assoc 20 MyList)) ;; include the '20' (setq Return (cdr (assoc 20 MyList))) ;; remove the '20' Quote
Saxlle Posted April 8 Posted April 8 Yes, you're right, agree. The only problem can be if you have the same "index", like: (setq MyList (list '(10 26509533.29 26509533.29 100.0) '(11 26509533.29 26509533.29 100.0) '(20 9985631.7 9985631.7 100.0) '(21 9985631.7 9985631.7 100.0) ;; same index value "21" '(30 6266660.57 6266660.57 20.0) '(21 9985631.7 9985631.7 100.0) ;; same index value "21" ) ; end list ) I haven't gone into depth on every possible problem, but it will work as expected. 1 Quote
Marcin O Posted April 8 Author Posted April 8 Dear @Saxlle, @Steven P thank You for Your answers and discusison. I think that code send by @Steven P Is what I was looking for. I've tried to implement 'solutions' from Excel into my script but there are much simpler and effective techniques I was not aware of. Thank You again for the answers Marcin 2 Quote
Recommended Posts
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.