Bagaimana cara mendapatkan nomor elemen dalam daftar?

16

T: bagaimana cara mendapatkan nomor elemen dalam daftar?

nthmendapat nomor elemen n dari daftar:

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

Saya ingin melakukan yang sebaliknya: dapatkan nomor elemen yang diberikan elemen:

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

Saya mungkin melewatkannya, tetapi apakah fungsi seperti itu ada? Bagaimana seseorang melakukan ini?

Dan
sumber

Jawaban:

22
  1. Berikut adalah fungsi yang disertakan dengan Emacs 24.3 dan yang lebih baru:
(cl-position 2 '(6 7 8 2 3 4)) ;; => 3

(Sebelum Emacs 24.3, gunakan fungsi positiondari perpustakaan cl.el, yang disertakan dengan Emacs.)

Anda dapat menggunakan :testkata kunci untuk menentukan fungsi perbandingan:

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

Manual Emulasi Common Lisp Emacs

  1. dash.el memiliki fungsi yang dapat melakukan ini: -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

Ini tidak termasuk dengan Emacs, tapi banyak pengguna Emacs sudah memilikinya diinstal (itu adalah ketergantungan projectile, flycheckdan smartparens, yang memberikan satu ton cakupan).

pengasuh
sumber
6

Nah, jika Anda ingin menggulung sendiri alih-alih menggunakan cl-position, dan Anda tidak ingin melintasi dua kali (menggunakan 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)))

Itu bagus bahkan untuk versi Emacs lama. Namun, ini memiliki perbedaan perilaku ini, yang Anda mungkin atau mungkin tidak ingin: Ini berfungsi juga untuk mobil-mobil dari daftar bertitik. Artinya, itu dengan benar mengembalikan posisi daripada meningkatkan kesalahan, untuk sexps seperti (nth-elt 'c '(a b c . d)).

Jika Anda ingin selalu meningkatkan kesalahan untuk daftar yang tidak benar, maka Anda ingin memeriksa untuk kasus itu, yang mengharuskan selalu melintasi ke akhir daftar:

(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
sumber
2

Ternyata itu adalah fungsi sederhana untuk menulis, meskipun mungkin tidak terlalu efisien:

(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

Saya lebih suka solusi bawaan jika ada, tentu saja.

Dan
sumber