Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
一个函数,用于标识一个字符串在lisp中包含在另一个字符串中的次数_Lisp_Common Lisp - Fatal编程技术网

一个函数,用于标识一个字符串在lisp中包含在另一个字符串中的次数

一个函数,用于标识一个字符串在lisp中包含在另一个字符串中的次数,lisp,common-lisp,Lisp,Common Lisp,我阻止编程lisp函数,该函数标记一个字符串包含在另一个字符串中的次数 我尝试了此函数,它向我发送了一个错误: ***-+:“abc”不是一个数字 (defun string-contain (string1 string2) (cond ((not (length string1)) nil) ; string1 est vide (pas besoin de le tester à chaque fois) ((> (length string1) (length st

我阻止编程lisp函数,该函数标记一个字符串包含在另一个字符串中的次数

我尝试了此函数,它向我发送了一个错误:

***-+:“abc”不是一个数字

(defun string-contain (string1 string2)
  (cond
   ((not (length string1)) nil) ; string1 est vide (pas besoin de le tester à chaque fois)
   ((> (length string1) (length string2)) nil) ; string1 est plus longue que chaine2
   ((string= string1 (subseq string2 0 (length string1))) string1) 
   (t (+ 1(string-include string1 (subseq string2 1))))))

感谢您查看代码,这看起来像是错误的来源:

((string= string1 (subseq string2 0 (length string1))) string1)
此行将返回一个字符串,如果比较成功,它可能会返回“1加上检查string1是否位于“string2的开头,前面一个字符”的值


在默认情况下(不匹配),您可能还希望跳过
(+1…
)。在基本情况下,您肯定希望返回0,而不是
nil

查看代码,这看起来像是错误的来源:

((string= string1 (subseq string2 0 (length string1))) string1)
此行将返回一个字符串,如果比较成功,它可能会返回“1加上检查string1是否位于“string2的开头,前面一个字符”的值


在默认情况下(不匹配),您可能还希望跳过
(+1…
)。在基本情况下,您肯定希望返回0,而不是
nil

(不是(长度字符串))
将始终为false或表示类型错误。您可能希望将0与
zerop

(不是(长度字符串))
进行比较,它将始终为false或表示类型错误。您可能希望将0与
zerop

进行比较,您的函数有三个肉眼可以注意到的问题:

  • (不是(长度字符串1))
    将始终是
    nil
    ,正如斯万特指出的那样
  • 函数在两个分支中返回
    nil
    ,在最后一个分支中返回一个数字。这种不一致性将来可能会导致问题
  • 没有函数
    字符串include
  • 下面是我将如何处理这个问题。我们要计算一个给定字符串包含在另一个字符串中的次数。这可分为以下几种情况:

    • 如果第一个字符串(“子字符串”)比第二个字符串短,则答案必须为0
    • 如果第一个字符串的长度等于第二个字符串的长度这些字符串相等,则答案必须是1
    • 如果第一个字符串比第二个字符串短,但从一开始就是它的一部分,我们发现1个包含项,加上,我们需要检查第二个字符串的其余部分(尾部)是否包含相同的子字符串
    • 任何其他内容都必须导致0
    下面是实现它的代码:

    (defun substring-times (substr string)
      (cond ((> (length substr) (length string)) 0)
            ((and (= (length substr) (length string))
                  (string= substr string))
             1)
            ((string= substr (subseq string 0 (length substr)))
             (1+ (substring-times substr (subseq string (length substr)))))
            (t 0)))
    
    我们可以在上面测试

    > (substring-times "ab" "abababababc")
    5
    
    此函数不包括“cabxabyab”中包含“ab”的情况。但变化是微不足道的(正如他们喜欢在书中所说的,只是一个练习)

    更有趣的是,这种函数效率很低(它在迭代的地方使用递归),并且在公共Lisp中不是惯用的。最好使用迭代重写它:

    (defun substring-times (substr string)
      (let ((sublen (length substr))
            (len (length string))
            (result 0)
            (i 0))
        (loop
           while (<= i (- len sublen))
           if (string= substr string :start2 i :end2 (+ i sublen))
           do (progn
                (incf result)
                (incf i sublen))
           else
           do (incf i)
           end
           finally (return result))))
    

    编辑:我已经用Rainer Joswig建议的
    string=
    关键字替换了
    subseq

    你的函数有三个肉眼可见的问题:

  • (不是(长度字符串1))
    将始终是
    nil
    ,正如斯万特指出的那样
  • 函数在两个分支中返回
    nil
    ,在最后一个分支中返回一个数字。这种不一致性将来可能会导致问题
  • 没有函数
    字符串include
  • 下面是我将如何处理这个问题。我们要计算一个给定字符串包含在另一个字符串中的次数。这可分为以下几种情况:

    • 如果第一个字符串(“子字符串”)比第二个字符串短,则答案必须为0
    • 如果第一个字符串的长度等于第二个字符串的长度这些字符串相等,则答案必须是1
    • 如果第一个字符串比第二个字符串短,但从一开始就是它的一部分,我们发现1个包含项,加上,我们需要检查第二个字符串的其余部分(尾部)是否包含相同的子字符串
    • 任何其他内容都必须导致0
    下面是实现它的代码:

    (defun substring-times (substr string)
      (cond ((> (length substr) (length string)) 0)
            ((and (= (length substr) (length string))
                  (string= substr string))
             1)
            ((string= substr (subseq string 0 (length substr)))
             (1+ (substring-times substr (subseq string (length substr)))))
            (t 0)))
    
    我们可以在上面测试

    > (substring-times "ab" "abababababc")
    5
    
    此函数不包括“cabxabyab”中包含“ab”的情况。但变化是微不足道的(正如他们喜欢在书中所说的,只是一个练习)

    更有趣的是,这种函数效率很低(它在迭代的地方使用递归),并且在公共Lisp中不是惯用的。最好使用迭代重写它:

    (defun substring-times (substr string)
      (let ((sublen (length substr))
            (len (length string))
            (result 0)
            (i 0))
        (loop
           while (<= i (- len sublen))
           if (string= substr string :start2 i :end2 (+ i sublen))
           do (progn
                (incf result)
                (incf i sublen))
           else
           do (incf i)
           end
           finally (return result))))
    

    编辑:正如Rainer Joswig所建议的那样,我已经用
    字符串=
    的关键字替换了
    subseq

    一般来说,当你处理字符串时,你应该尽量避免调用subseq,因为它会创建一个新字符串,你不想做所有的字符串分配。Common Lisp中的许多序列处理函数都采用开始和结束参数,因此您可以指定要查找的序列的哪些部分。函数search在另一个序列中查找一个序列的匹配项,并返回第一个匹配项的索引。您可以使用新的:start2值重复调用,以便在字符串中搜索得越来越远。例如:

    (defun search-all (needle haystack &key key (test 'eql)
                                         (start1 0)
                                         (end1 (length needle))
                                         (start2 0)
                                         (end2 nil)
                                         (overlaps nil))
      "Counts the number of times that NEEDLE appears in HAYSTACK. START1
    and END1, and START2 and END2, are bounding index designators of
    NEEDLE and HAYSTACK, respectively.  If OVERLAPS is true, then
    overlapping occurrences will be counted separately."
      (do* ((len1 (- end1 start1))           ; length of needle (constant)
            (upd (if overlaps 1 len1))       ; how much to increment pos
            (occurrences 0 (1+ occurrences)) ; occurrences, increments by 1
            (start2 start2 (+ pos upd))      ; start2, updated to pos+upd
            (pos #1=(search needle haystack  ; pos. of needle, or NIL
                            :start1 start1 :end1 end1
                            :start2 start2 :end2 end2
                            :test test :key key)
                 #1#)) 
           ((null pos) occurrences))) ; when pos is NIL, return occurrences
    
    其中有一点可能有点混乱。dodo*循环中的变量绑定具有以下形式(变量[init form[update form]]),我们希望pos的init form和update form相同,即调用search。在通用Lisp代码中,您可以使用#n=form,然后使用#n#稍后再次引用相同的表单。这就是为什么我使用#1=(search…作为初始表单,然后使用#1#作为更新表单

    以下是一些例子:

    ;; Find 'ab' within a 'abcdabcd'
    (SEARCH-ALL "ab" "abcdabcd")
    ;;=> 2
    
    ;; Find 'cat' within a 'one cat two cat three cat'
    (SEARCH-ALL "concatenate" "one cat two cat three cat" :START1 3 :END1 6)
    ;;=> 3
    
    ;; Find 'cat' within 'one cat two cat'
    (SEARCH-ALL "concatenate" "one cat two cat three cat" :START1 3 :END1 6 :START2
                0 :END2 15)
    ;;=> 2
    
    ;; Fail to find 'cat' in 'Cat'
    (SEARCH-ALL "cat" "Cat")
    ;;=> 0
    
    ;; Find 'cat' in 'Cat'
    (SEARCH-ALL "cat" "Cat" :TEST 'CHAR-EQUAL)
    ;;=> 1
    
    ;; Find 2 'aaa' in 'baaaaaab' (no overlaps)
    (SEARCH-ALL "aaa" "baaaaaab" :OVERLAPS NIL)
    ;;=> 2
    
    ;; Find 4 'aaa' in 'baaaaaab' (with overlaps)
    (SEARCH-ALL "aaa" "baaaaaab" :OVERLAPS T)
    ;;=> 4