我需要用对填充列表,例如:((x 10)(z 5))。
我目前的方法:
;;send the current list, and an id value pair
(define (setID idList ID VAL)
(cond
;;if the list is null, add the pair
((null? idList) (cons '(ID VAL) '()))
;; if the ID already exists, overwrite it
((equal? ID (car(car idList))) (cons '((cdr idList)) VAL))
;; continue the search
(else (setID (cdr idList) ID VAL))
)
)
我意识到我还需要使用cons
来保持列表的正确性,但第一个问题是当我执行(setID z 5)
之类的操作时,返回的列表正好是:((id val))
。显然,它需要((z 10))
。反正有没有做过这样的事情?
答案 0 :(得分:2)
您的代码存在三个主要问题:
(cons '(ID VAL) '()))
您正在构建一个值为(ID VAL)
的新对 - 也就是说,第一个元素是符号ID
第二个是符号VAL
。这不是您想要的,您需要ID
的值和VAL
的值。确保您了解quote
的工作方式ID
时,您必须将新修改的对与列表的其余部分一起使用cons
到输出。请记住:我们在遍历列表时正在构建答案这就是我的意思:
;;send the current list, and an id value pair
(define (setID idList ID VAL)
(cond
;;if the list is null, add the pair
((null? idList) (cons (list ID VAL) '()))
;; if the ID already exists, overwrite it
((equal? ID (car (car idList))) (cons (list ID VAL) (cdr idList)))
;; continue the search
(else (cons (car idList) (setID (cdr idList) ID VAL)))))
并且不要忘记执行此过程后返回的列表是 new ,如果要继续添加元素,则必须将其存储在某处或作为参数传递它 - 因为最初作为参数收到的列表保持不变。现在程序按预期工作:
(setID '() 'x 10)
=> '((x 10))
(setID '((x 10)) 'y 20)
=> '((x 10) (y 20))
(setID '((x 10) (y 20)) 'x 30)
=> '((x 30) (y 20))
答案 1 :(得分:1)
不要重新发明轮子,关联列表在方案中很常见
这里的易事是带头标的守卫。以便((x 10)(z 5))
成为(*idList* (x 10)(z 5))
;;send the current list, and an id value pair
(define (setID! idList ID VAL)
;;if a function mutates data end it with a bang
(let ((ID-VAL (assoc ID (cdr idList))))
;;assoc returns #f if no match, with the ID-VAL pair if there is a match
(if ID-VAL
(set-car! (cdr ID-VAL) VAL)
;; if the ID already exists, overwrite it
(set-cdr! idList (cons (list ID VAL) (cdr idList)))))
;;if ID into in assoc-list, add the pair
idList) ;;return the idList
测试
(setID! '(*idList*) 'x 10)
;Value 3: (*idlist* (x 10))
(setID! '(*idlist* (x 10)) 'y 20)
;Value 4: (*idlist* (y 20) (x 10))
(setID! '(*idlist* (y 20) (x 10)) 'x 30)
;Value 9: (*idlist* (y 20) (x 30))
答案 2 :(得分:1)
这是来自@WorBlux的答案的Racket-y版本:
你的" setID
"基本上已在Racket中以dict-set
的名称定义。
(dict-set dict key v) → (and/c dict? immutable?) dict : (and/c dict? immutable?) key : any/c v : any/c
通过将
dict
映射到key
来功能扩展v
,覆盖key
的任何现有映射,并返回扩展字典。如果exn:fail:contract
不支持功能扩展或dict
不是字典的允许密钥,则更新可能会失败,并显示key
异常。示例:
> (dict-set #hash() 'a "apple") '#hash((a . "apple")) > (dict-set #hash((a . "apple") (b . "beer")) 'b "banana") '#hash((b . "banana") (a . "apple")) > (dict-set '() 'a "apple") '((a . "apple")) > (dict-set '((a . "apple") (b . "beer")) 'b "banana") '((a . "apple") (b . "banana"))
参见上面的最后两个例子。
当然,您可以使用dict-ref
和其他功能按键查找值,或映射它们,依此类推。
请注意,dict-set
与您描述的略有不同,因为assoc
(由dict
}使用(key . val)
而不是(key val)
。换句话说,它使用(cons key val)
而不是(list key val)
。使用(cons a b)
而不是(cons a (cons b '()))
存储两个项目效率更高。