Replace Lisp:多级搜索和替换

Replace Lisp:多级搜索和替换,replace,lisp,Replace,Lisp,我想写一个lisp函数,在字符串中进行多次搜索和替换。例如,我想在字符串bat中分别用e和d替换a和t,从而生成bed 如何执行此操作?如果您希望一次替换原始字符串中的一个字符,与unix实用程序的工作方式类似,您应该执行以下操作并收集转换后的字符: (defun transform-chars (replacements str) "replacements is a list of lists: (FROM-CHAR TO-CHAR)" (coerce (loop for c

我想写一个lisp函数,在字符串中进行多次搜索和替换。例如,我想在字符串bat中分别用e和d替换a和t,从而生成bed


如何执行此操作?

如果您希望一次替换原始字符串中的一个字符,与unix实用程序的工作方式类似,您应该执行以下操作并收集转换后的字符:

(defun transform-chars (replacements str)
  "replacements is a list of lists: (FROM-CHAR TO-CHAR)"
  (coerce
    (loop for char across str
          for tr = (assoc char replacements)
          if (null tr) collect char
          else collect (second tr))
    'string))

(transform-chars '((#\a #\e) (#\t #\d)) "bat")
我在这些子条款中使用循环宏:


此外,我们正在进行。

如果您希望一次替换原始字符串中的一个字符,与unix实用程序的工作方式类似,您应该执行以下操作并收集转换后的字符:

(defun transform-chars (replacements str)
  "replacements is a list of lists: (FROM-CHAR TO-CHAR)"
  (coerce
    (loop for char across str
          for tr = (assoc char replacements)
          if (null tr) collect char
          else collect (second tr))
    'string))

(transform-chars '((#\a #\e) (#\t #\d)) "bat")
我在这些子条款中使用循环宏:


此外,我们还提供了。

这是一个纯功能版本:

(map 'string (lambda (c)
               (case c
                 (#\a #\e)
                 (#\t #\d)
                 (t c)))
     "bat")
==> "bed"
为了使其更通用,您可以在编译时使用宏构造lambda:

(defmacro make-translation-lambda (from to)
  `(lambda (c) (case c ,@(map 'list (lambda (i o) `(,i ,o)) from to) (t c))))
(map 'string (make-translation-lambda "at" "ed") "bat")
==> "bed"
请注意,宏make translation lambda的参数必须是字符串文字

或者,更灵活但效率更低,您可以这样做

(defun translate-string (input from to)
  (assert (= (length from) (length to)))
  (map 'string
       (lambda (c)
         (let ((pos (position c from)))
           (if pos
               (char to pos)
               c)))
       input))
(translate-string "bed" "at" "ed")
==> "bed"
使用宏make translation lambda的版本的性能与被转换为输入的字符串成线性关系


函数translate string的性能是olengInput*lengthfrom。

这里是一个纯函数版本:

(map 'string (lambda (c)
               (case c
                 (#\a #\e)
                 (#\t #\d)
                 (t c)))
     "bat")
==> "bed"
为了使其更通用,您可以在编译时使用宏构造lambda:

(defmacro make-translation-lambda (from to)
  `(lambda (c) (case c ,@(map 'list (lambda (i o) `(,i ,o)) from to) (t c))))
(map 'string (make-translation-lambda "at" "ed") "bat")
==> "bed"
请注意,宏make translation lambda的参数必须是字符串文字

或者,更灵活但效率更低,您可以这样做

(defun translate-string (input from to)
  (assert (= (length from) (length to)))
  (map 'string
       (lambda (c)
         (let ((pos (position c from)))
           (if pos
               (char to pos)
               c)))
       input))
(translate-string "bed" "at" "ed")
==> "bed"
使用宏make translation lambda的版本的性能与被转换为输入的字符串成线性关系

函数translate string的性能是olengInput*lengthfrom。

仅用于记录:

(defun make-sparse-charmap (from to)
  (loop with map =
       (loop with map = (make-string 128 :initial-element #\x)
          for i from 0 below 128 do
            (setf (char map i) (code-char i))
          finally (return map))
     for x across from
     for y across to do
       (setf (char map (char-code x)) y)
     finally (return map)))

(defun tr (source from to)
  (loop with map = (make-sparse-charmap from to)
     and result = (make-string (length source) :initial-element #\x)
     for c across source
     for i from 0 do
       (setf (char result i) (char map (char-code c)))
     finally (return result)))
对于Unicode字符串可能不是最好的主意,但是对于ASCII将很好

编辑

对其进行了轻微修改,使其无需额外生成lambda。

仅用于记录:

(defun make-sparse-charmap (from to)
  (loop with map =
       (loop with map = (make-string 128 :initial-element #\x)
          for i from 0 below 128 do
            (setf (char map i) (code-char i))
          finally (return map))
     for x across from
     for y across to do
       (setf (char map (char-code x)) y)
     finally (return map)))

(defun tr (source from to)
  (loop with map = (make-sparse-charmap from to)
     and result = (make-string (length source) :initial-element #\x)
     for c across source
     for i from 0 do
       (setf (char result i) (char map (char-code c)))
     finally (return result)))
对于Unicode字符串可能不是最好的主意,但是对于ASCII将很好

编辑


稍微修改一下,不需要额外生成lambdas。

请发布您已经编写的代码。请发布您已经编写的代码。我想投票支持您,但您能解释一下为什么要创建稀疏字符映射吗?它是用来处理大量替换的吗?@omouse sparse charmap暗指Emacs中经常使用的名称,它是一种哈希表/数组/b树结构,用于存储对所键入键的函数引用。它是稀疏的,因为它有一个默认值,它只返回你给它的任何东西,你添加的所有东西都是额外的功能。然而,在Emacs中,它不是数组。但对于较小的字母集,数组将是一个非常有效的解决方案。我想投票支持你,但你能解释一下为什么要创建稀疏字符映射吗?它是用来处理大量替换的吗?@omouse sparse charmap暗指Emacs中经常使用的名称,它是一种哈希表/数组/b树结构,用于存储对所键入键的函数引用。它是稀疏的,因为它有一个默认值,它只返回你给它的任何东西,你添加的所有东西都是额外的功能。然而,在Emacs中,它不是数组。但对于较小的字母集,数组将是一个非常有效的解决方案。@arbautjc,请将这种类型的编辑作为注释发布,它似乎被拒绝了。我不明白为什么,但没关系。。。除非是错误的,必须用if替换。nullp不是CL的一部分,它是null。这是强制的“字符串,而不是”序列。我不觉得这种评论很有用,因为omouse的逻辑显然是正确的,而且几乎没有编码错误。继续为有兴趣的人介绍meta:@arbautjc你被拒绝了,因为版主不知道编程语言,你的编辑是正确的。@omouse:不,除了格式、打字之外的代码编辑,大写和错误的变量名通常是无效的,而像您刚才对编程语言中我知道或不知道的东西所做的假设是不好的。它属于一个评论。很高兴你修复了它。@arbautjc,请将这种类型的编辑作为评论发布,它似乎被拒绝了。我不明白为什么,但没关系。。。除非是错误的,必须用if替换。nullp不是CL的一部分,它是null。这是强制的“字符串,而不是”序列。我不觉得这种评论很有用,因为omouse的逻辑显然是正确的,而且几乎没有编码错误。继续为有兴趣的人介绍meta:@arbautjc你被拒绝了,因为版主不知道编程语言,你的编辑是正确的。@omouse:不,除了格式、打字之外的代码编辑,大写和错误的变量名通常是无效的,就像你刚才对我在prog方面知道或不知道的东西所做的假设一样 冲压语言很糟糕。它属于一个评论。不过很高兴你修好了。