LISP:计算子字符串以检查事件

时间:2015-04-04 10:02:54

标签: lisp

(defun count-sub (str pat)
 (loop with z = 0 with s = 0 while s do
       (when (setf s (search pat str :start6 s))
         (incf z) (incf s (length pat)))
       finally (return z))))

是的,所以我有这个代码来计算子字符串,但它一次只需要子字符串输入,我如何让它接受更多的输入?

即。所以输入就像:

(count-sub“abcde”“a”“d”“e”“c”)

而不仅仅是: (count-sub“abcd”“a”)

1 个答案:

答案 0 :(得分:0)

我会这样,以便一元函数具有不同的名称:

(defun count-sub-1 (str pat)
 (loop with z = 0 with s = 0 while s do
       (when (setf s (search pat str :start2 s)) ;; :start6 typo fixed
         (incf z) (incf s (length pat)))
       finally (return z))))

然后,N-ary API函数只是减少了这个工作:

(defun count-sub (str &rest patterns)
  (reduce #'+ patterns :key (lambda (item) (count-sub-1 str item))))

一些测试:

(count-sub "aabc") -> 0
(count-sub "aabc" "a") -> 2
(count-sub "aabc" "a" "a") -> 4
(count-sub "aabc" "b") -> 1
(count-sub "aabc" "a" "b") -> 3

但是你的逻辑中有一个错误。如果模式是空字符串,则会得到无限循环,因为(incf s (length pat))不会更改s的值:

(count-sub "abc" "") -> #<non-termination!>

可能的解决方法是:

(incf s (min (length pat) 1))
如果长度匹配为零,则

始终前进至少一个字符。在这种情况下,空字符串将在目标字符串中多次匹配;如果这是不合需要的(你希望一个空模式导致零),那么必须对其进行检查:

(if (plusp (length pat))
  (loop ...)
  0)

然后不需要(min (length pat) 1)补偿。