Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.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
List 在Lisp中更改列表的副本,而不更改原始列表_List_Lisp - Fatal编程技术网

List 在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) (

如何在不更改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) (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:您可以编辑您的问题以使其有用。