LISP - 元素位置
Lisp - 在序列中查找元素
Section titled “Lisp - 在序列中查找元素”Common Lisp 提供了多功能的 position 函数,用于查找序列(如列表或向量)中元素的索引。序列的第一个索引是 0。
(position item sequence &key :from-end :test :key :start :end)参数与返回值
Section titled “参数与返回值”item:要搜索的元素。sequence:要在其中搜索的列表、向量或字符串。- 返回值:找到的第一个匹配元素的零基索引。如果未找到该项,则返回
NIL。
在列表中查找项
Section titled “在列表中查找项”;; 查找符号 'c 的位置(position 'c '(a b c d e c)) ; -> 2
;; 搜索一个不存在的项(position 'z '(a b c d e)) ; -> NIL在向量中查找项
Section titled “在向量中查找项”;; 向量的语法是 #( ... )(position #\d #(#\a #\b #\c #\d)) ; -> 3使用关键字参数自定义搜索
Section titled “使用关键字参数自定义搜索”position 函数的强大之处在于它的可选关键字参数。
:from-end t:从序列的末尾而不是开头开始搜索。:start index:从指定的index开始搜索。:end index:在指定的index之前停止搜索。:test function:一个用于比较项与序列元素的函数。这对于非默认的相等性检查至关重要。:key function:在比较发生之前应用于序列每个元素的函数。
示例::from-end 和 :start
Section titled “示例::from-end 和 :start”;; 查找 'c 的最后一个出现位置(position 'c '(a b c d c f) :from-end t) ; -> 4
;; 从索引 3 开始查找 'c'(position 'c '(a b c d c f) :start 3) ; -> 4深入探讨::test 参数与相等性
Section titled “深入探讨::test 参数与相等性”初学者常犯的一个错误是未能理解 Lisp 中不同的相等性函数。position 的默认 :test 是 #'eql,这在比较字符串或列表时可能不是你想要的结果。
eq:比较内存地址。仅当是完全相同的对象时才为真。eql(默认):类似于eq,但对于相同的字符和相同类型的数字也为真。equal:递归地比较值。如果字符串具有相同的字符,或者列表具有相同的equal元素,则为真。equalp:一个更宽松的equal。在字符串中忽略大小写,并比较数值而不考虑类型(例如,(equalp 2 2.0)为真)。
示例:搜索列表或字符串
Section titled “示例:搜索列表或字符串”;; 这返回 NIL,因为两个 "foo" 字符串是不同的对象。(position "foo" '("bar" "foo" "baz")) ; -> NIL
;; 这可行,因为 `equal` 比较的是字符串内容。(position "foo" '("bar" "foo" "baz") :test #'equal) ; -> 1
;; 查找子列表(position '(1 2) '((1 1) (1 2) (1 3)) :test #'equal) ; -> 1使用 :key 参数进行强大搜索
Section titled “使用 :key 参数进行强大搜索”:key 参数在复杂数据结构内部进行搜索时非常有用。它允许你指定要查看每个元素的哪个部分。
示例:搜索属性列表 (plists) 的列表
Section titled “示例:搜索属性列表 (plists) 的列表”(defvar *people* '((:name "Alice" :age 30) (:name "Bob" :age 25) (:name "Charlie" :age 35)))
;; 查找名为 "Bob" 的人的位置。;; :key 在比较前从每个人的属性列表 (plist) 中提取名称。(position "Bob" *people* :key #'(lambda (person) (getf person :name)) :test #'string-equal) ; string-equal 是一个不区分大小写的相等比较函数1