假设有一个名为xs
的列表。此列表需要通过谓词进行过滤,并且需要从结果中获取随机元素:
(rand-nth (filter pred? xs))
这将返回列表中的一个项目。如果另外需要保留原始列表(减去提取的项目),该怎么办?
这两个步骤是必要的还是有更快的方法?
(let [item (rand-nth (filter pred? xs))
new-xs (remove (partial = item) xs)]
...)
答案 0 :(得分:1)
对于输入xs
中的重复元素,您的解决方案将失败,因为随机选择所有重复项都会将其删除。
我宁愿自己选择随机索引并直接使用它:
(defn remove-nth [xs n]
(when (seq xs)
(if (vector? xs)
(concat
(subvec xs 0 n)
(subvec xs (inc n) (count xs)))
(concat
(take n xs)
(drop (inc n) xs)))))
(defn remove-random [xs]
(if (seq xs)
(let [index (rand-int (count xs))
item (nth xs index)
remaining (remove-nth xs index)]
[item remaining])))
答案 1 :(得分:1)
您也可以在不保留item
的绑定的情况下执行此操作:
user> (defn split-rnd [pred coll]
(let [[l [it & r]] (split-with (complement
#{(rand-nth (filter pred coll))})
coll)]
[it (concat l r)]))
#'user/split-rnd
user> (split-rnd pos? [-1 2 -3 4 -5 6 -7])
[4 (-1 2 -3 -5 6 -7)]
user> (split-rnd pos? [-1 2 -3 4 -5 6 -7])
[6 (-1 2 -3 4 -5 -7)]
user> (split-rnd pos? [-1 2 -3 4 -5 6 -7])
[2 (-1 -3 4 -5 6 -7)]