5

According to documentation, member checks if a a given element is an element of a list. For example if the list, say my_list consists of apple and orange, (member "apple" my_list) returns true.

Is there an easy way to check if a given string is a part of a string of a list. For example ap is a part of a string of the above list. Hence it would be desirable to have a function like my-function such that (my-function "ap" my_list) returns true.

6

The easiest way is to use the Common Lisp compatibility layer:

(require 'cl-seq)
(cl-member "ap" '("foo" "apa" "bar") :test #'string-match)
==> ("apa" "bar")

PS. This is not directly relevant to your question, but if you have a few minutes to kill, keep reading. ;-)

Note that Emacs maintainers have traditionally eschewed CL (starting with the original political animosity of RMS towards the CL creators).

See Controversy of Common Lisp Package in Emacs Lisp for attempts to justify the hostility in technical terms.

4

The function that comes to my mind at least would be cl-member using a string-match-p test.

Here's a short example that shows how to use it:

ELISP> (setq testing '("an apple" "a pear" "a grape"))
("an apple" "a pear" "a grape")

ELISP> (cl-member "apple" testing)
nil
ELISP> (cl-member "an apple" testing)
nil
ELISP> (cl-member "an apple" testing :test #'string=)
("an apple" "a pear" "a grape")

ELISP> (cl-member "a pear" testing :test #'string=)
("a pear" "a grape")

ELISP> (cl-member "a pear" testing :test #'string-match-p)
("a pear" "a grape")

ELISP> (cl-member "pear" testing :test #'string-match-p)
("a pear" "a grape")

ELISP> (cl-member "xx" testing :test #'string-match-p)
nil

Note that member and cl-member doesn't actually return true but the sublist that contains the sought element. That in turn will eventually evaluates to true in tests, but That's mostly a minor detail.

Edit:

Sean pointed out an important detail about string-match and string-match-p: Regular expression meta-characters in the search string might give an erroneous result. If that's a problem you could examine the raw sequence instead with cl-search:

ELISP> (setq test (list "apple" "pear" "grape"))
("apple" "pear" "grape")

ELISP> (cl-member "ap" test :test #'cl-search)
("apple" "pear" "grape")

ELISP> (cl-member "gra" test :test #'cl-search)
("grape")
  • Hopefully there are no regular expression metacharacters in your search string... – Sean Nov 16 '16 at 19:22
1

A solution that almost doesn't require cl-lib (only cl-defgeneric and cl-defmethod):

(seq-some (lambda (x) (string-match "foo" x)) '("f" "fo" "fooo"))

And a solution that doesn't require cl-lib

(defun some-string-matches (search strings)
  (while (and strings (not (string-match search (car strings))))
    (setq strings (cdr strings)))
  strings)

Just so it would live up to the title.

  • This is elegant. – Name Nov 16 '16 at 16:01
  • @npostavs it would be simply wrong if it were :) let me check. I thought it was Emacs' own. – wvxvw Nov 16 '16 at 16:34
  • @npostavs yeah, you are right. But let me search for a bit. I cannot believe Emacs Lisp doesn't have one of its own... – wvxvw Nov 16 '16 at 16:37
  • @npostavs but there's seq-filter! :P – wvxvw Nov 16 '16 at 16:39
  • Bummer, this one is also from CL-variety... hm. – wvxvw Nov 16 '16 at 16:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.