Wie bekomme ich die Elementnummer in eine Liste?

16

F: Wie erhalte ich die Elementnummer in einer Liste?

ntherhält Elementnummer n aus einer Liste:

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

Ich würde gerne das Gegenteil tun: Erhalte die Elementnummer bei gegebenem Element:

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

Ich habe es vielleicht verpasst, aber gibt es eine solche Funktion? Wie würde man das machen?

Dan
quelle

Antworten:

22
  1. Hier ist eine Funktion, die in Emacs 24.3 und höher enthalten ist:
(cl-position 2 '(6 7 8 2 3 4)) ;; => 3

(Verwenden Sie vor Emacs 24.3 die in Emacs enthaltene Funktion positionaus der Bibliothek cl.el.)

Sie können das :testSchlüsselwort verwenden, um die Vergleichsfunktion anzugeben:

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

Emacs Common Lisp-Emulationshandbuch

  1. dash.el hat eine Funktion, die das kann: -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

Es ist nicht mit Emacs enthalten, aber viele Emacs Benutzer bereits installiert (es ist eine Abhängigkeit von projectile, flycheckund smartparens, was ihm eine Tonne Abdeckung gibt).

Kindermädchen
quelle
6

Nun, wenn Sie Ihre eigenen würfeln möchten, anstatt zu verwenden cl-position, und Sie nicht zweimal (mit length) durchqueren möchten ...

(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)))

Das ist auch für alte Emacs-Versionen gut. Es weist jedoch diesen Verhaltensunterschied auf, den Sie möglicherweise möchten oder nicht möchten: Es funktioniert auch für die Autos einer gepunkteten Liste. Das heißt, es gibt die Position korrekt zurück, anstatt einen Fehler auszulösen, für Sexps wie (nth-elt 'c '(a b c . d)).

Wenn Sie für eine unzulässige Liste immer einen Fehler auslösen möchten, sollten Sie nach diesem Fall suchen, bei dem immer zum Ende der Liste übergegangen werden muss:

(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)))
Drew
quelle
2

Es hat sich herausgestellt, dass das Schreiben eine einfache Funktion ist, auch wenn sie möglicherweise nicht so effizient ist:

(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

Ich würde natürlich eine eingebaute Lösung vorziehen, wenn es eine gibt.

Dan
quelle