代码之家  ›  专栏  ›  技术社区  ›  BlueBadger

CommonLisp:删除函数,它是如何使用的?

  •  5
  • BlueBadger  · 技术社区  · 16 年前

    我想从字符串中去掉第一个正斜杠,我查阅了函数 remove

    我已经使用此代码设置了请求uri。

    (setq request-uri "/node/143")
    

    当我检查变量时,我返回了这个。

    request-uri
    "/node/143"
    

    我现在尝试删除第一个斜杠(在这一点上,看看函数是如何正确使用的)。

    (remove "/" request-uri)
    "/node/143"
    
    (remove '/ request-uri)
    "/node/143"
    

    (remove '("/") request-uri)
    "/node/143"
    
    (remove '('/) request-uri)
    "/node/143"
    

    即使字符串是 vectors of characters

    (remove "/node/143" request-uri)
    "/node/143"
    
    (remove '/node143 request-uri)
    "/node/143"
    

    所以我现在不知所措,这个看似简单的函数真的让我不知所措,我本以为我完全按照文档进行了操作,但什么都没用。

    谢谢

    从我使用的字符串中删除一个元素

    (remove #\/ request-uri)
    

    `(remove #\node request-uri`)
    

    只对第一个字符有效并抛出错误,而后面的所有字符都不起作用。

    (remove "node" request-uri)
    (remove 'node request-uri)
    (remove ?\node request-uri)
    (remove #\node request-uri)
    (remove '("node") request-uri)
    

    我不知道这里还应该怎么说。

    4 回复  |  直到 16 年前
        1
  •  7
  •   Rainer Joswig mmmmmm    5 年前

    学会阅读 Common Lisp HyperSpec

    弦是 Sequences Arrays (字符的一维向量)以及, Strings . 这意味着这些功能中的大多数都是适用的。

    让我们看看 REMOVE . CLHS签字如下:

    remove item sequence &key from-end test test-not start end count key
        => result-sequence
    

    (remove #\/ "/foo/")
    

    或(例如)

    (remove #\/ "/foo/" :start 2)
    

    记得: #\a 是一个人物。 #\node 这不是性格。不合法的一串是 "/foo/" .

     (remove "/" "/abc/" :key #'string :test #'equal)
    

    这将查看序列中的每个字符,并将其转换为字符串。然后将该字符串与您的项目进行比较 "/" 使用相等的函数。这也行得通。代价是它需要从每个字符中生成一个字符串 "/abc/" ,每个字符串都是一个新对象。

    另一种方法是:

     (remove "/" "/abc/" :test (lambda (a b) (eql (aref a 0) b)))
    

    上面检索的第一个字符 "/" 并将其与字符串中的字符进行比较 . 同样,代价是需要获得五次字符(在本例中)。

    因此,如果原始对象以字符串形式出现,那么最好的编写方法是:

    (remove (aref "/" 0) "/abc/")
    

    上面我们从字符串中获取字符 once and then REMOVE将此字符与字符串中的每个字符的默认EQL测试进行比较-它将返回一个新的字符串,其中包含不属于EQL的字符 #\/ .

    你期望什么?\foo是什么?在公共Lisp中,这是符号 |?fOO| .

    (remove "foo" "afoob") 从字符串开始不起作用( "foo" 仍然是字符串而不是字符。因此 "/" #\/ 它们是不同类型的。第一个是字符串,第二个是字符。

    SUBSEQ从序列中提取序列。这意味着它还会从另一个字符串中提取一个字符串:

    (subseq "0123456" 1 5)
         where 1 is the start and 5 is the end index.
    

    连接附加序列。这意味着它还附加字符串。

    (concatenate 'string "abc" "123")
      returns a new string with the strings "abc" and "123" appended.
    

    要删除字符串的某些部分,请参见函数string-TRIM、string-LEFT-TRIM和string-RIGHT-TRIM。

    搜索在字符串中搜索字符串。

        2
  •  2
  •   Svante    16 年前

    要删除整个子字符串,您必须创建一个新函数,例如:

    (defun remove-string (rem-string full-string &key from-end (test #'eql)
                          test-not (start1 0) end1 (start2 0) end2 key)
      "returns full-string with rem-string removed"
      (let ((subst-point (search rem-string full-string 
                                 :from-end from-end
                                 :test test :test-not test-not
                                 :start1 start1 :end1 end1
                                 :start2 start2 :end2 end2 :key key)))
        (if subst-point
            (concatenate 'string
                         (subseq full-string 0 subst-point)
                         (subseq full-string (+ subst-point (length rem-string))))
            full-string)))
    

    这只是一个起点。我复制了搜索的所有选项,但我认为有些选项在这种情况下没有意义。至少这是可行的:

    (remove-string "node" "this is a node or not")
    

    对于更复杂的情况,您可能应该看看CLPPCRE,一个正则表达式库。

        3
  •  2
  •   Anonymous Coward    16 年前

    说明:

    (remove "node" request-uri)
    (remove 'node request-uri)
    (remove ?\node request-uri)
    (remove #\node request-uri)
    (remove '("node") request-uri)
    

    它们分别是:一个字符串、一个(带引号的)符号、一个(已计算的)符号、一个格式错误的字符文本和一个包含一个字符串的列表。 REMOVE

    如果您只想删除字符串的一部分,SUBSEQ可能会执行以下操作:

    (let ((uri "/node/143"))
      (when (string= (subseq uri 0 6) "/node/")
        (format t "user wants node ~D" (parse-integer (subseq uri 6)))))
    

    对于更复杂的事情,您可能需要像cl-ppcre和/或split-sequence这样的库。(如果您正在使用Hunchentoot,则已加载前者。)

        4
  •  0
  •   Tung Nguyen    16 年前

    此操作失败,因为“/”是字符串,而不是字符。

    (remove "/" request-uri)
    "/node/143"
    

    如果需要字符,则需要使用#/即正斜杠字符。

    (remove #\/ request-uri)
    "node143"
    

    但正如你所看到的,它会被移除 全部的 前斜杠。根据您链接的文档页面,remove采用名为:count的关键字参数,该参数表示要删除的项目数。所以你可以这样做。

    (remove #\/ request-uri :count 1)
    "node/143"
    

    ::编辑::

    不是?/,是#/。谢谢道格拉斯!