¿Cómo obtener el número de elemento en una lista?


16

P: ¿cómo obtengo el número de elemento en una lista?

nthobtiene el elemento número n de una lista:

(nth 2 '(a b c d))                      ; => c

Me gustaría hacer lo contrario: obtener el número de elemento dado el elemento:

(some-function 'c '(a b c d))           ; => 2

Puede que me lo haya perdido, pero ¿existe tal función? ¿Cómo haría uno esto?

Respuestas:


22
  1. Aquí hay una función que se incluye con Emacs 24.3 y posterior:
(cl-position 2 '(6 7 8 2 3 4)) ;; => 3

(Antes de Emacs 24.3, use la función positionde la biblioteca cl.el, que se incluye con Emacs).

Puede usar la :testpalabra clave para especificar la función de comparación:

(cl-position "bar" '("foo" "bar" "baz") :test 'equal) ;; => 1
(cl-position '(1 2) '((3) (5 6) (1 2) nil) :test 'equal) ;; => 2

Manual de emulación Emacs Common Lisp

  1. dash.el tiene una función que puede hacer esto: -elem-index
(-elem-index 2 '(6 7 8 2 3 4)) ;; => 3
(-elem-index "bar" '("foo" "bar" "baz")) ;; => 1
(-elem-index '(1 2) '((3) (5 6) (1 2) nil)) ;; => 2

No está incluido con Emacs, pero una gran cantidad de usuarios de Emacs lo tiene instalado (que es una dependencia de projectile, flychecky smartparens, lo que le da un montón de cobertura).


6

Bueno, si quieres rodar el tuyo en lugar de usar cl-position, y no quieres atravesar dos veces (usando length) ...

(defun nth-elt (element xs)
  "Return zero-indexed position of ELEMENT in list XS, or nil if absent."
  (let ((idx  0))
    (catch 'nth-elt
      (dolist (x  xs)
        (when (equal element x) (throw 'nth-elt idx))
        (setq idx  (1+ idx)))
      nil)))

Eso es bueno incluso para versiones antiguas de Emacs. Sin embargo, tiene esta diferencia de comportamiento, que podría desear o no: también funciona para los automóviles de una lista de puntos. Es decir, devuelve correctamente la posición en lugar de generar un error, para sexps como (nth-elt 'c '(a b c . d)).

Si siempre desea generar un error para una lista incorrecta, entonces querrá verificar ese caso, que requiere siempre desplazarse hasta el final de la lista:

(defun nth-elt (element xs)
  "Return zero-indexed position of ELEMENT in list XS, or nil if absent."
  (let ((idx  0))
    (when (atom (cdr (last xs))) (error "Not a proper list"))
    (catch 'nth-elt
      (dolist (x  xs)
        (when (equal element x) (throw 'nth-elt idx))
        (setq idx  (1+ idx)))
      nil)))

2

Resulta que es una función simple de escribir, aunque puede que no sea tan eficiente:

(defun nth-elt (elt list)
  "Return element number of ELT in LIST."
  (let ((loc (length (member elt list))))
    (unless (zerop loc)
      (- (length list) loc))))

(nth-elt 'c '(a b c d))                 ; => 2
(nth-elt 'f '(a b c d))                 ; => nil

Preferiría una solución integrada si existe, por supuesto.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.