也许使用interleave
> (interleave [1 2 3] [:a :b :c] ["X" "Y"])
(1 :a "X" 2 :b "Y")
所以,比如这样
(defn people->groups
[people n-groups]
(let [group-size (quot (count people) n-groups)]
(->> (group-by :office people)
(map (comp shuffle second))
(apply interleave)
(partition group-size group-size []))))
使用如下所示
> (def ppl (for [i (range 100)] (let [office (rand-nth [:a :b :c])] {:name (str office "-" i) :office office})))
#'ppl
> (rand-nth ppl)
{:name ":a-19", :office :a}
> (people->groups ppl 4)
...
一些想法
有一些边缘情况需要处理,这取决于您认为当人员数量不能均匀分配到组数量时会发生什么。当前实现会怎么做?为什么?确保“正确”的事情发生是一个有趣的练习 - 也许先做测试然后再固定您喜欢的行为。
从一系列地图开始,就像您有的那样,是很好的 - 我会这么做
您的代码暗示 ngroups
是某些非局部可解引用的,函数参数可能更有意义
我发现我几乎总是可以用clojure.core
中的东西重写使用 loop/first/rest
的代码。尽可能多地学习clojure.core
。
希望这有助于。玩得开心!您已经走在正确的轨道上了。