List 在Lisp中更改列表的副本,而不更改原始列表
如何在不更改Common Lisp中原始列表的元素的情况下更改列表副本的元素?使用List 在Lisp中更改列表的副本,而不更改原始列表,list,lisp,List,Lisp,如何在不更改Common Lisp中原始列表的元素的情况下更改列表副本的元素?使用copy-list复制列表。您可以删除或添加新列表的元素,而旧列表不会更改。复制列表复制其参数列表的顶级结构。如果要通过手术修改其中的值,还需要复制它们 [3]> (defvar a (list (list 1 2) (list 3 4) 5 (list 6))) ((1 2) (3 4) 5 (6)) [4]> (defvar b (copy-list a)) B [5]> b ((1 2) (
copy-list
复制列表。您可以删除或添加新列表的元素,而旧列表不会更改。复制列表复制其参数列表的顶级结构。如果要通过手术修改其中的值,还需要复制它们
[3]> (defvar a (list (list 1 2) (list 3 4) 5 (list 6)))
((1 2) (3 4) 5 (6))
[4]> (defvar b (copy-list a))
B
[5]> b
((1 2) (3 4) 5 (6))
[6]> (setf (third b) 55)
55
[7]> b
((1 2) (3 4) 55 (6))
[8]> a
((1 2) (3 4) 5 (6)) ;; top level value changed independently
[9]> (setf (second (second b)) 44)
44
[10]> b
((1 2) (3 44) 55 (6))
[11]> a
((1 2) (3 44) 5 (6)) ;; deeper change reflected in the original
因此,在进行更深入的更改之前,一定要进行更深入的复制,如(setf(第二个b)(复制列表(第二个a))
,首先:
[12]> (setf (second b) (copy-list (second a)))
(3 44)
[13]> (setf (second (second b)) 444)
444
[14]> b
((1 2) (3 444) 55 (6))
[15]> a
((1 2) (3 44) 5 (6))
您需要创建新的
cons
,直到要替换的元素。例如
; example
(defparameter *test* '(1 2 (3 4 5 6) 7 8))
;; change 4 in the structure in *test* to 99
(list* (car *test*)
(cadr *test*)
(list* (caaddr *test*)
99 ; the actual change
(cdaddr *test*)) ; shared sublist tail
(cdddr *test*)) ; shared tail
; ==> (1 2 (3 99 4 5 6) 7 8)
在这里,子列表的结尾和主列表的结尾共享结构,因为它不需要更改
如何搜索树并将一个子树替换为另一个子树:
;; replace all occurences of target in source with replacement
(defun find-replace (source target replacement)
(cond ((equal source target) replacement) ;; equal, return replacement
((not (consp source)) source) ;; not equal && not pair, return source
(t (cons (find-replace (car source) target replacement) ;; recurse
(find-replace (cdr source) target replacement)))))
(find-replace *test* 4 99) ; ==> (1 2 (3 99 4 5 6) 7 8)
(find-replace *test* '(3 4 5 6) "banan") ; ==> (1 2 "banan" 7 8)
不清楚你在问什么。一个非常直接的答案是“复制列表,并修改副本而不是原始副本”。但这不太可能是您想要的,因此我们需要更多的细节。@Joshua Taylor:这不是不可能的,因为列表中的结构共享在Lisp中非常常见。“什么是复制品,什么不是复制品,可能不容易弄清楚。”雷纳·约瑟维格我同意。这就是OP需要提供更多信息的原因(例如,提出了什么样的修改,需要什么样的副本,等等)。“直接”答案的作用范围是“复制”意味着为了“修改”而需要的任何意思。我的程序是迷宫解算器。程序从文本文件中读取迷宫作为列表,并读取战略点的编号。我的问题是,当程序处理第一个起始点时,它会更改迷宫列表,并使用+字符标记路径。然后,当考虑第二个起点时,迷宫列表会根据第一个起点发生变化。我希望迷宫列表不会随着每个起点而改变。我试过复制列表,但不起作用。如果您有任何想法,我们将不胜感激。@Arwa Alsubhi:您可以编辑您的问题以使其有用。