2011-10-27 24 views
2

使用set!我希望能夠修改本地狀態list變量lst,但只有它的使用set修改列表的一部分?

例如,我要插入的內部列表中值的部分:

((1 2) (4 5)) 

變得

((1 2 3) (4 5)) 

我希望能夠像做set! (car lst) (append (car lst) 3)

但是,這似乎只修改由(car lst)生成的臨時變量。

我能想到的唯一方法是用新的期望值創建一個新列表,並將lst設置爲新列表,但這似乎是浪費和不必要的。有沒有更好的方法來做到這一點?

+0

他們都列出了嗎?或缺點?我的意思是,它是這樣定義的:(define lst(list(list 1 2)(list 4 5)))? – galchen

+0

是的,這是所有的列表 – robev

回答

2

試試這個:

(define lst (list (list 1 2) (list 4 5))) 
lst 
> ((1 2) (4 5)) 
(set-cdr! (cdar lst) (list 3)) 
lst 
> ((1 2 3) (4 5)) 

修改時利弊/列表,你應該使用設置CDR!和集車!

編輯:爲球拍

使用可變名單:

(require racket/mpair) 
(define lst (mlist (mlist 1 2) (mlist 4 5))) 
lst 
> (mcons (mcons 1 (mcons 2 '())) (mcons (mcons 4 (mcons 5 '())) '())) 
(set-mcdr! (mcdr (mcar lst)) (list 3)) 
> (mcons (mcons 1 (mcons 2 #<promise:temp2>)) (mcons (mcons 4 (mcons 5 '())) '())) 
lst 
+0

對不起,我使用的球拍(應該更清楚),它沒有設置車! – robev

0

根據該方案的解釋你使用,你可能需要做更多的工作。例如,在球拍列表原語可變默認狀態下,你將不得不使用的程序的可變版本:

(require scheme/mpair) 
(define lst (mlist (mlist 1 2) (mlist 4 5))) 
lst 
(set-mcdr! (mcdr (mcar lst)) (mlist 3)) 
lst 
-1

方案的標準成語零星創建列表是冠以元素前面,使用cons,而不是嘗試set-cdr!列表中的最後一個cons單元格。最後,列表完成後,您可以使用reverse以正確的順序獲取元素。這樣,本身不需要列表突變。

所以,如果你想創建列表(1 2 3)零碎:

  • 與空單,()開始關閉,cons 1到它。這給你(1)
  • 然後cons 2到列表:(2 1)
  • 然後cons 3到列表:(3 2 1)
  • 最後,當你完成建築列表,扭轉這種局面:(1 2 3)

你可能會問爲什麼這個更好」。這是因爲訪問最後一對set-cdr!是O(n)操作;使用鏈表時,元素不是隨機訪問,而是在訪問的元素位置上是線性的。而cons總是O(1)。

reverse是一個O(n)操作,但只要在最後(當您準備按照正確的順序構建列表時)執行操作,而不是始終調用它,則不會對性能產生不利影響。

+0

是的,但這是關於設置!,而不是如何創建一個列表。我想修改一個本地狀態變量。 – robev