我正在寻找一种在列表中实现相等堆的方法,该列表可以接受N个元素的列表,并将其拆分为M个堆。任何余数都会逐个添加到每个堆中。我觉得可能已经有什么东西在那里了。
List: [1 2 3 4 5 6 7 8 9]
M = 5
[[1] [2] [3] [4] [5]]; divided into equal piles with remainder [6 7 8 9]
[[1 6] [2 7] [3 8] [4 9] [5]]; output但每堆中的实际数字我并不真正关心。只要(count元素)是所有其他元素中的+/-。
我找到了partion-all,但它没有以我需要的方式处理剩余部分,并且我无法让程序获取生成的列表的最后一个元素并将其放入前面的堆中。
发布于 2014-10-20 10:12:41
group-by-based解决方案(不保证w.r.t.堆排序)
如果列表中的项目可能不是从range获得的连续整数,您可以将迭戈函数背后的基本思想应用于索引,而不是项目本身:
(defn piles [m xs]
(->> xs
(map-indexed (fn [i x] [(mod i m) x]))
(group-by first)
vals
(mapv #(mapv peek %))))请注意,对于足够大的m值,group-by将返回一个散列映射,因此此函数不能保证堆的任何特定顺序(特别是,较短的堆可能先于较高的堆到达)。
REPL中的示例:
(piles 5 [1 2 3 4 5 6 7 8 9])
;= [[1 6] [2 7] [3 8] [4 9] [5]]
(piles 5 [:a :b :c :d :e :f :g :h :i])
;= [[:a :f] [:b :g] [:c :h] [:d :i] [:e]]桩间交替的partition-all-based解
或者,您可以使用partition-all和自定义版本的map,该版本仅在其所有输入为空时停止:
(defn piles2 [m xs]
(letfn [(mapv-all [f & colls]
(loop [colls (map seq colls) ret []]
(if (every? nil? colls)
ret
(recur (map next colls)
(conj ret
(mapv first (take-while some? colls)))))))]
(->> xs
(partition-all m)
(apply mapv-all vector))))这个函数总是以“自然”的顺序返回堆。
示例:
(piles2 5 [:a :b :c :d :e :f :g :h :i])
;= [[:a :f] [:b :g] [:c :h] [:d :i] [:e]]保留原始项目顺序的partition-all-based解决方案
作为对评论的回应,这里有一种保持元素原始顺序的方法:
(defn piles3 [m xs]
(let [cnt (count xs)
l (quot cnt m)
r (rem cnt m)
k (* (inc l) r)]
(concat
(partition-all (inc l) (take k xs))
(partition-all l (drop k xs)))))注意:这将返回一个seq序列;您可以使用(mapv vec …)将其转换为向量的向量。
示例:
(piles3 5 (range 32))
;= ((0 1 2 3 4 5 6) (7 8 9 10 11 12 13) (14 15 16 17 18 19) (20 21 22 23 24 25) (26 27 28 29 30 31))
(map count *1)
;= (7 7 6 6 6)发布于 2014-10-20 10:03:25
你可以这样做:
(defn piles [xs m]
(vals (group-by #(mod % m) xs)))然后
(piles [1 2 3 4 5 6 7 8 9] 5)=> (1 6 3 8 5)
发布于 2014-10-21 18:48:05
一个简洁的-尽管缓慢-懒惰的解决方案:
(defn piles [n coll]
(let [heads (take n (iterate rest coll))]
(map (partial take-nth n) heads)))例如
(piles 5 (range 1 10))
;((1 6) (2 7) (3 8) (4 9) (5))https://stackoverflow.com/questions/26457225
复制相似问题