我真的是Lisp编程的新手,因此我更愿意自己摸索,所以任何提示都会感激不尽。我的目标是检索一个随机挑选的唯一项目的列表。下面的代码有时会返回一个列表,如("有一个球""有一个球")。我希望它能检查列表中的成员是否是唯一的,如果不是,则丢弃其中一个相同的项目,并添加一个随机的唯一成员。
(defvar *pirateAttributes*
(list "has a pirate costume" "has a wooden leg" "has a
ball")
)
(defun select-attributes (n)
(loop repeat n
collect (nth (random (length *pirateAttributes*))
*pirateAttributes*)
)
)
(select-attributes 2)
UPDATE1:我通过上网查了一大堆资料,不知怎么找到了一个方法,使它成功了。我相信还有更好的方法。由于我有一个工作版本,所以欢迎大家提供最佳答案! 这次我把循环保持得比较长,决定修剪或使用递归来获得所需的属性量。如果有很多属性的话,它的扩展性可能会很差,但它是这样的......
(defun select-attributes (n)
"returns n randomly picked attributes from *pirateAttributes* as a list"
(setf mylist '())
(loop repeat (+ n 10)
do (push (nth (random (length *pirateAttributes*)) *pirateAttributes*) mylist)
(print mylist)
)
(setf mylist (remove-duplicates mylist) )
(print mylist)
(setf listlen (length mylist))
(case n
(1 (if(= listlen 1)(values)(setf mylist (first mylist))))
(2 (if(= listlen 2)(values)(setf mylist (cdr mylist))))
(3 (if(= listlen 3)(values)(select-attributes n)))
)
)
一个合理的简单的解决方案是将属性列表并执行 费舍尔-耶茨洗牌 上。
你可以创建一个函数,返回一个包含属性列表中洗牌元素的新列表。列表中的 shuffle
下面的函数从输入列表中随机选择一个元素,并把它放到洗牌剩余元素的结果上。
然后你可以使用 subseq
函数从洗牌后的列表中获取你需要的元素数量。
(defvar *pirate-attributes*
(list "has a pirate costume"
"has a wooden leg"
"has a ball"
"has a parrot"
"has a monkey"
"has a saber"
"has an eye patch"
"has a bottle of rum"))
(defun shuffle (xs)
(if (or (null xs)
(null (cdr xs)))
xs
(let* ((i (random (length xs)))
(x (nth i xs)))
(cons x (shuffle (append (subseq xs 0 i)
(subseq xs (1+ i))))))))
(defun select-random-n (xs n)
(subseq (shuffle xs) 0 n))
REPL交互示例:
CL-USER> (select-random-n *pirate-attributes* 3)
("has a bottle of rum" "has a pirate costume" "has an eye patch")
CL-USER> (select-random-n *pirate-attributes* 3)
("has an eye patch" "has a ball" "has a bottle of rum")
CL-USER> (select-random-n *pirate-attributes* 2)
("has a monkey" "has a parrot")
CL-USER> (select-random-n *pirate-attributes* 5)
("has a ball" "has a saber" "has an eye patch" "has a wooden leg"
"has a parrot")
CL-USER> (select-random-n *pirate-attributes* 5)
("has a wooden leg" "has a monkey" "has a ball" "has a pirate costume"
"has a parrot")