如何将一个集合分成两个部分给出的百分比

时间:2012-07-21 15:26:46

标签: clojure

我有一个我想以任意百分比分割的集合。我想解决的实际问题是将数据集拆分为训练和交叉验证集。

应该随机选择每个元素的目标,但每个源元素在结果中只出现一次,并且分区的大小是固定的。如果源集合具有重复项,则重复项可能出现在不同的输出分区中或相同。

我有这个实现:

(defn split-shuffled
  "Returns a 2 element vector partitioned by the percentage 
   specified by p. Elements are selected at random. Each 
   element of the source collection will appear only once in 
   the result."
  [c p]
  (let [m (count c)
        idxs (into #{} (take (* m p) (shuffle (range m))))
        afn (fn [i x] (if (idxs i) x))
        bfn (fn [i x] (if-not (idxs i) x))]
    [(keep-indexed afn c) (keep-indexed bfn c)]))

repl> (split-shuffled (range 10) 0.2)
[(4 6) (0 1 2 3 5 7 8 9)]

repl> (split-shuffled (range 10) 0.4)
[(1 4 6 7) [0 2 3 5 8 9)] 

但我很高兴keep-indexed被召唤两次。

如何改进?

编辑:我原本想保留分区中的顺序,但是我没有重新考虑就放弃了这个要求,所以@mikera的解决方案是正确的!

1 个答案:

答案 0 :(得分:5)

为什么你需要索引?

直接将收藏品洗牌:

(defn split-shuffled
     [c p]
     (let [c (shuffle c)
           m (count c)
           t (* m p)]
       [(take t c) (drop t c)]))