Author Topic: (vl-position return multiple Index  (Read 9888 times)

0 Members and 1 Guest are viewing this topic.

mailmaverick

  • Bull Frog
  • Posts: 493
(vl-position return multiple Index
« on: December 01, 2015, 06:45:20 PM »
(vl-position returns index of first occurrence of an item in a list.

How to get all indexes of occurences of an item in a list.

For example :-

(setq item 2)
(setq itemlist (list 2 3 4 5 6 2 3 4 2 3 4 2 6 5))

I want return value :

(list 0 5 8 11)


Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: (vl-position return multiple Index
« Reply #1 on: December 01, 2015, 06:48:22 PM »
One possible method:
Code - Auto/Visual Lisp: [Select]
  1. (defun vl-positions ( x l / i )
  2.     (setq i -1)
  3.     (vl-remove nil (mapcar '(lambda ( y ) (setq i (1+ i)) (if (= x y) i)) l))
  4. )
Code - Auto/Visual Lisp: [Select]
  1. _$ (vl-positions 2 '(2 3 4 5 6 2 3 4 2 3 4 2 6 5))
  2. (0 5 8 11)
« Last Edit: December 01, 2015, 06:53:11 PM by Lee Mac »

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: (vl-position return multiple Index
« Reply #2 on: December 01, 2015, 06:52:55 PM »
Another:
Code - Auto/Visual Lisp: [Select]
  1. (defun vl-positions ( x l / p )
  2.     (if (setq p (vl-position x l))
  3.         (cons p (mapcar '(lambda ( y ) (+ 1 p y)) (vl-positions x (cdr (member x l)))))
  4.     )
  5. )

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: (vl-position return multiple Index
« Reply #3 on: December 01, 2015, 07:13:42 PM »
Looking in my old lisp items I found these:
Code: [Select]
;;  CAB  10/18/2005
;;  returns a list of pointers (base 0) of the
;;  item found in the list
(defun getpos (itm lst / idn nlst)
  (setq idx -1)
  (while (< (setq idx (1+ idx)) (length lst))
    (and (= itm (nth idx lst))
         (setq nlst (cons idx nlst))))
  (reverse nlst)
)

;; (print (GetPos 3 '(1 2 3 1 2 3 1 3 5)))
;;  returns (2 5 7)

   
;;  CAB  12/17/2009
;;  returns a list of pointers (base 0) of the
;;  item found in the list
(defun getpos (pat lst / i plst)
  (setq i 0)
  (mapcar
    (function
      (lambda (x)
        (and (wcmatch x pat) (setq plst (cons i plst)))
        (setq i (1+ i))))
    lst)
  (reverse plst))

(defun c:test()
  (princ (getpos "*25" '("0425" "123" "345" "625")))
  (princ)
  )


And these:
Code: [Select]
;;  CAB  05/22/2009
;;+++++++++++++++++++++++++++++++++++++++++++++++++++++
;;  Return a sub list starting at the nth position and
;;  with all the remaining items
;;+++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun nth+ (lst idx)
  (repeat idx
    (setq lst (cdr lst))
  )
  lst
)

;;  http://www.theswamp.org/index.php?topic=7269.0
;;  CAB  10/15/2005
;;+++++++++++++++++++++++++++++++++++++++++++++++++++++
;;  Return a sub list starting at the nth position and
;;  with the number of items specified by num  0= all remaining items
;;+++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun nth+ (lst idx num / newlst)
  (and (or (numberp num) (setq num 0)) ; force all
       (zerop num) ; if zero
       (setq num (length lst)) ; all
  )
  (repeat num
    (setq newlst (cons (nth idx lst) newlst)
          idx (1+ idx))
  )
  (reverse (vl-remove nil newlst))
)

(defun c:test()
  (print (nth+ '(1 2 3 4 5) 0 2)) ; |-> (1 2) 
  (print (nth+ '(1 2 3 4 5) 3 2)) ; |-> (4 5) 
  (print (nth+ '(1 2 3 4 5) 4 5)) ; |-> (5)   
  (print (nth+ '(1 2 3 4 5) 6 2)) ; |-> nil   
  (print (nth+ '(1 2 3 4 5) 2 0)) ; |-> (3 4 5)
  (princ)
)

;;  CAB  10/15/2005
;;+++++++++++++++++++++++++++++++++++++++++++++++++++++
;;  Return a sub list starting at the nth position and
;;  with the number of items specified by num
;;+++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun nth+ (idx ; start position 0 = first item
             lst ; list of items
             num ; number of items to return  0= all remaining items
             / newlst)
  (and (or (numberp num) ; catch non numbers
           (setq num 0)) ; force all
       (zerop num) ; if zero
       (setq num (length lst)) ; all
  )
  (repeat num
    (setq newlst (cons (nth idx lst) newlst)
          idx (1+ idx))
  )
  (reverse (vl-remove nil newlst))
)

(defun c:test()
  (print (nth+ 0 '(1 2 3 4 5) 2)) ; |-> (1 2) 
  (print (nth+ 3 '(1 2 3 4 5) 2)) ; |-> (4 5) 
  (print (nth+ 4 '(1 2 3 4 5) 5)) ; |-> (5)   
  (print (nth+ 6 '(1 2 3 4 5) 2)) ; |-> nil   
  (print (nth+ 2 '(1 2 3 4 5) 0)) ; |-> (3 4 5)
  (princ)
)

;;=======================================================
;;  David B
;;  http://cadtutor.net/forum/showpost.php?p=218577&postcount=9
(defun sublst (l s n / tmp)
   (repeat n (setq tmp (cons (nth s l) tmp))
             (setq s (1+ s)))
   (reverse tmp))
       
       
       
(setq l1 '(1 2 3 4 5 6 7))
(prin1 (sublst l1 2 4))


;;=======================================================
;;  by ASMI  extract nth position items
;;  http://cadtutor.net/forum/showpost.php?p=218187&postcount=5

(defun Extract-List-Items(Lst Items)
  (mapcar '(lambda(i)(nth i Lst))Items)
  )
 
 
Command: (Extract-List-Items '(a b c d e f) '(0 4 5))
(A E F)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1453
  • Marco
Re: (vl-position return multiple Index
« Reply #4 on: December 02, 2015, 04:49:49 AM »
Others:
Code: [Select]
; Function: ALE_PositionS - 2014/04/09
(defun ALE_PositionS (i l / c r)
  (setq c -1)
  (vl-every
    (function
      (lambda (x)
        (setq c (1+ c))
        (if (equal i x) (setq r (cons c r)) T)
      )
    )
    l
  )
  (reverse r)
)
Code: [Select]
; Function: ALE_PositionS2 - 01/09/2005
;
; Version 1.00
;
; Description:
;   returns the positions of a item in a list (nth based)
;
; Arguments:
;   TstItm = Any AutoLISP symbol
;   In_Lst = A true list
;
; Return Values:
;   List or nil if TstItm is not member of the list
;
; Examples:
;   (setq alist '(0 1 2 3 4 3 5 3 6 3 3 7))
;
;   (ALE_PositionS 3 alist)
;   Returns: (3 5 7 9 10)
;
;
(defun ALE_PositionS2 (TstItm In_Lst / LstLen OutLst)
  (setq LstLen (1- (length In_Lst)))
  (while (vl-position TstItm In_Lst)
    (setq
      In_Lst (cdr (member TstItm In_Lst))
      OutLst (cons (- LstLen (length In_Lst)) OutLst)
    )
  )
  (reverse OutLst)
)

ronjonp

  • Needs a day job
  • Posts: 7529
Re: (vl-position return multiple Index
« Reply #5 on: December 02, 2015, 10:08:09 AM »
My offering .. not the fastest but a little different :) 

Code - Auto/Visual Lisp: [Select]
  1. (defun nths (itm l / ln out)
  2.   (and l (setq ln (1- (length l))))
  3.   (while (setq l (member itm l)) (setq out (cons (- ln (length (setq l (cdr l)))) out)))
  4.   (reverse out)
  5. )
Tested on a list of 600 items:
Quote
Benchmarking ...............Elapsed milliseconds / relative speed for 4096 iteration(s):


    (VL-POSITIONS 2 L)........1828 / 8.34 <fastest>
    (NTHS 2 L)................1844 / 8.27
    (ALE_POSITIONS 2 L).......1906 / 8.00
    (ALE_POSITIONS2 2 L)......1953 / 7.81
    (GETPOS 2 L)..............8969 / 1.70
    (VL-POSITIONS2 2 L)......15250 / 1.00 <slowest>
« Last Edit: December 02, 2015, 12:03:53 PM by ronjonp »

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1453
  • Marco
Re: (vl-position return multiple Index
« Reply #6 on: December 02, 2015, 11:41:21 AM »
My offering .. not the fastest but a little different :)

Code - Auto/Visual Lisp: [Select]
  1. (defun nths (itm l / ln out)
  2.   (and l (setq ln (1- (length l))))
  3.   (while (setq l (cdr (member itm l))) (setq out (cons (- ln (length l)) out)))
  4.   (reverse out)
  5. )
Tested on a list of 600 items:
Ron your get a little error:

Comando: (NTHS 1 '(1 2 3 1 4 5 6 1))
(0 3)

Comando: (NTHS 1 '(1 2 3 1 4 5 6 1 1 1 1))
(0 3 7 8 9)

ronjonp

  • Needs a day job
  • Posts: 7529
Re: (vl-position return multiple Index
« Reply #7 on: December 02, 2015, 12:03:20 PM »
DOH! Fixed above :)

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1453
  • Marco
Re: (vl-position return multiple Index
« Reply #8 on: December 02, 2015, 12:03:37 PM »
My offering .. not the fastest but a little different :)
...
Ron your get a little error:

Comando: (NTHS 1 '(1 2 3 1 4 5 6 1))
(0 3)

Comando: (NTHS 1 '(1 2 3 1 4 5 6 1 1 1 1))
(0 3 7 8 9)
This is my version for vanilla lisp:
Code: [Select]
; 2005/09/01
(defun ALE_PositionS2m (i l / n r)
  (setq n (1- (length l)))
  (while (setq l (member i l))
    (setq
      l (cdr l)
      r (cons (- n (length l)) r)
    )
  )
  (reverse r)
)
;(ALE_Positions2m 1 '(1 2 3 1 4 5 6 1 1 1 1)) => (0 3 7 8 9 10)

ronjonp

  • Needs a day job
  • Posts: 7529
Re: (vl-position return multiple Index
« Reply #9 on: December 02, 2015, 12:08:43 PM »
Interesting .. now the benchmark puts it at the top  :D
Quote
Benchmarking ...............Elapsed milliseconds / relative speed for 4096 iteration(s):


    (NTHS 2 L)................1250 / 13.00 <fastest>
    (ALE_POSITIONS 2 L).......1359 / 11.96
    (ALE_POSITIONS2 2 L)......1359 / 11.96
    (VL-POSITIONS 2 L)........1485 / 10.94
    (GETPOS 2 L)..............8125 / 2.00
    (VL-POSITIONS2 2 L)......16250 / 1.00 <slowest>

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Tharwat

  • Swamp Rat
  • Posts: 710
  • Hypersensitive
Re: (vl-position return multiple Index
« Reply #10 on: December 02, 2015, 01:04:49 PM »
Another.

Code - Auto/Visual Lisp: [Select]
  1. (defun M-position (itm lst / i p)
  2.   (setq i 0)
  3.   (foreach n lst
  4.     (if (eq n itm) (setq p (cons i p)))
  5.     (setq i (1+ i))
  6.   )
  7.   (reverse p)
  8. )
  9.  

ronjonp

  • Needs a day job
  • Posts: 7529
Re: (vl-position return multiple Index
« Reply #11 on: December 02, 2015, 02:29:44 PM »
Seems like if you're going to process an entire list, a quick check to see if there are any values that meet the condition would greatly speed up the function if none are found. Thoughts?

Code - Auto/Visual Lisp: [Select]
  1. (defun m-position (itm lst / i p)
  2.   (setq i 0)
  3.   (if (member itm lst)
  4.     (foreach n lst
  5.       (if (eq n itm)
  6.         (setq p (cons i p))
  7.       )
  8.       (setq i (1+ i))
  9.     )
  10.   )
  11.   (reverse p)
  12. )
« Last Edit: December 02, 2015, 02:47:00 PM by ronjonp »

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Tharwat

  • Swamp Rat
  • Posts: 710
  • Hypersensitive
Re: (vl-position return multiple Index
« Reply #12 on: December 02, 2015, 02:38:03 PM »
Agreed  with ron.

If I would re-write the codes based on ron's mods , I would remove the progn function and move the setting of the variable ( i ) to the top again. :whistling:

ronjonp

  • Needs a day job
  • Posts: 7529
Re: (vl-position return multiple Index
« Reply #13 on: December 02, 2015, 02:47:18 PM »
Agreed  with ron.

If I would re-write the codes based on ron's mods , I would remove the progn function and move the setting of the variable ( i ) to the top again. :whistling:
*Fixed  ;)

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Stefan

  • Bull Frog
  • Posts: 319
  • The most I miss IRL is the Undo button
Re: (vl-position return multiple Index
« Reply #14 on: December 02, 2015, 02:49:35 PM »
Another one, for long lists
Code - Auto/Visual Lisp: [Select]
  1. (defun index (n l / i j r)
  2.   (setq j -1)
  3.   (while
  4.     (setq i (vl-position n l))
  5.     (setq r (cons (setq j (+ 1 i j)) r))
  6.     (setq l (cdr (member n l)))
  7.     )
  8.   (reverse r)
  9.   )