LISP查找和替换

LISP查找和替换,lisp,common-lisp,Lisp,Common Lisp,我目前正在解决一些初学者的Lisp问题。我正在使用公共Lisp 下面我尝试实现一个基本的查找和替换:char1是要在列表中搜索的字符,char2是要替换的字符,而list to search是我正在搜索的列表 (defun find-and-replace (char1 char2 list-to-search &optional (ammended-list(list))) (cond ((null list-to-search) ammended-list) ((e

我目前正在解决一些初学者的Lisp问题。我正在使用公共Lisp

下面我尝试实现一个基本的查找和替换:char1是要在列表中搜索的字符,char2是要替换的字符,而list to search是我正在搜索的列表

(defun find-and-replace (char1 char2 list-to-search &optional (ammended-list(list)))
  (cond
   ((null list-to-search) ammended-list) 
   ((eql char1 (car list-to-search))
    (append ammended-list (list char2))
    (find-and-replace char1 char2 (cdr list-to-search)))
   (t (append ammended-list
              (list (car list-to-search))
              (find-and-replace char1 char2 (cdr list-to-search))))))
当我跑步时:

(find-and-replace '1 'z '(1 2 3 1 4 5)) => (2 3 4 5)
如我所料:

(z 2 3 z 4 5)
问题:

1
是一个数字
z
是一个符号。您的代码与字符无关,字符是CommonLisp中的实际数据类型

如果没有正确的格式和缩进,Lisp编程将变得极其困难

函数
append
没有副作用

append
应该避免,因为它很昂贵

由于使用递归,函数可以处理的列表的长度受到堆栈大小的限制。通常情况下,您可能会使用
mapcar

问题:

1
是一个数字
z
是一个符号。您的代码与字符无关,字符是CommonLisp中的实际数据类型

如果没有正确的格式和缩进,Lisp编程将变得极其困难

函数
append
没有副作用

append
应该避免,因为它很昂贵


由于使用递归,函数可以处理的列表的长度受到堆栈大小的限制。通常在上,您可能会使用
mapcar

append
不修改参数列表,您需要将结果赋回变量。在进行递归调用时,您没有传递修改后的列表,因此它总是使用初始值
nil

(defun find-and-replace (char1 char2 list-to-search &optional (ammended-list(list)))
  (cond
   ((null list-to-search) ammended-list) 
   ((eql char1 (car list-to-search))
    (setq ammended-list (append ammended-list (list char2))
    (find-and-replace char1 char2 (cdr list-to-search) ammended-list))
   (t (setq ammended-list (append ammended-list (list char1))
      (find-and-replace char1 char2 (cdr list-to-search) ammended-list))))
不过,这不是编写函数的最佳方式
APPEND
是一项昂贵的操作,每次都要复制列表。最好是一次构建一个元素的新列表:

(defun find-and-replace(char1 char2 list-to-search)
  (cond ((null list-to-search) nil)
        ((eql char1 (car list-to-search))
         (cons char2 (find-and-replace char1 char2 (cdr list-to-search))))
        (t (cons (car list-to-search) (find-and-replace char1 char2 (cdr list-to-search))))))

append
不修改参数列表,需要将结果赋回变量。在进行递归调用时,您没有传递修改后的列表,因此它总是使用初始值
nil

(defun find-and-replace (char1 char2 list-to-search &optional (ammended-list(list)))
  (cond
   ((null list-to-search) ammended-list) 
   ((eql char1 (car list-to-search))
    (setq ammended-list (append ammended-list (list char2))
    (find-and-replace char1 char2 (cdr list-to-search) ammended-list))
   (t (setq ammended-list (append ammended-list (list char1))
      (find-and-replace char1 char2 (cdr list-to-search) ammended-list))))
不过,这不是编写函数的最佳方式
APPEND
是一项昂贵的操作,每次都要复制列表。最好是一次构建一个元素的新列表:

(defun find-and-replace(char1 char2 list-to-search)
  (cond ((null list-to-search) nil)
        ((eql char1 (car list-to-search))
         (cons char2 (find-and-replace char1 char2 (cdr list-to-search))))
        (t (cons (car list-to-search) (find-and-replace char1 char2 (cdr list-to-search))))))

append
不修改列表,它返回一个新列表。
append
不修改列表,它返回一个新列表。谢谢Barmar。修订后的守则似乎是解决这一问题的更明智的办法。我用(cons(要搜索的汽车列表))替换了最后一行,因为这正是我想要的。但是谢谢你。希望我能用这种思维方式来解决一些未来的问题。谢谢Barmar。修订后的守则似乎是解决这一问题的更明智的办法。我用(cons(要搜索的汽车列表))替换了最后一行,因为这正是我想要的。但是谢谢你。希望我能用这种思维方式来解决一些未来的问题。