LISP - position of Element
Lisp - Finding Elements in a Sequence
Section titled “Lisp - Finding Elements in a Sequence”Common Lisp provides the versatile position function to find the index of an element within a sequence (like a list or a vector). The first index of a sequence is 0.
Syntax
Section titled “Syntax”(position item sequence &key :from-end :test :key :start :end)Arguments & Return Value
Section titled “Arguments & Return Value”item: The element to search for.sequence: The list, vector, or string to search in.- Returns: The zero-based index of the first matching element found. If the item is not found, it returns
NIL.
Basic Examples
Section titled “Basic Examples”Finding an item in a list
Section titled “Finding an item in a list”;; Find the position of the symbol 'c(position 'c '(a b c d e c)) ; -> 2
;; Search for an item that doesn't exist(position 'z '(a b c d e)) ; -> NILFinding an item in a vector
Section titled “Finding an item in a vector”;; The syntax for a vector is #( ... )(position #\d #(#\a #\b #\c #\d)) ; -> 3Customizing the Search with Keyword Arguments
Section titled “Customizing the Search with Keyword Arguments”The power of position comes from its optional keyword arguments.
:from-end t: Starts the search from the end of the sequence instead of the beginning.:start index: Starts the search at the specifiedindex.:end index: Stops the search before the specifiedindex.:test function: A function used to compare the item with sequence elements. This is crucial for non-default equality checks.:key function: A function applied to each element of the sequence before the comparison happens.
Example: :from-end and :start
Section titled “Example: :from-end and :start”;; Find the last occurrence of 'c(position 'c '(a b c d c f) :from-end t) ; -> 4
;; Find 'c' starting from index 3(position 'c '(a b c d c f) :start 3) ; -> 4A Deeper Look: The :test Argument and Equality
Section titled “A Deeper Look: The :test Argument and Equality”A common pitfall for beginners is not understanding Lisp’s different equality functions. The default :test for position is #'eql, which may not be what you want for comparing strings or lists.
eq: Compares memory addresses. True only for the exact same object.eql(the default): Likeeq, but also true for identical characters and numbers of the same type.equal: Compares values recursively. True if strings have the same characters or lists have the sameequalelements.equalp: A more permissiveequal. Ignores case in strings and compares numeric values regardless of type (e.g.,(equalp 2 2.0)is true).
Example: Searching for a list or string
Section titled “Example: Searching for a list or string”;; This returns NIL because the two "foo" strings are different objects.(position "foo" '("bar" "foo" "baz")) ; -> NIL
;; This works because `equal` compares string content.(position "foo" '("bar" "foo" "baz") :test #'equal) ; -> 1
;; Find a sublist(position '(1 2) '((1 1) (1 2) (1 3)) :test #'equal) ; -> 1Powerful Searches with the :key Argument
Section titled “Powerful Searches with the :key Argument”The :key argument is incredibly useful for searching inside complex data structures. It lets you specify what part of each element to look at.
Example: Searching a list of property lists (plists)
Section titled “Example: Searching a list of property lists (plists)”(defvar *people* '((:name "Alice" :age 30) (:name "Bob" :age 25) (:name "Charlie" :age 35)))
;; Find the position of the person named "Bob".;; The :key extracts the name from each person's plist before comparison.(position "Bob" *people* :key #'(lambda (person) (getf person :name)) :test #'string-equal) ; string-equal is a case-insensitive equalResult
Section titled “Result”1