我想使用clojure来划分特定的集合:
例如:
有一个向量[1 2 3 4 5]
。此处还有一个地图,如{2 1, 3 1}
,这意味着生成包含2个元素的1个集合,以及包含3个元素的1个集合。
(some_function {2 1, 3 1} [1 2 3 4 5])
;; I only want to these:
(([1 2 3] [4 5])
([1 2 4] [3 5])
([1 2 5] [3 4])
([1 2] [3 4 5])
([1 3 4] [2 5])
([1 3 5] [2 4])
([1 3] [2 4 5])
([1 4 5] [2 3])
([1 4] [2 3 5])
([1 5] [2 3 4]))
以前,我曾考虑使用(combo/partitions [1 1 2])
来生成所有案例,然后根据条件进行过滤,但是当你有一个像[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17]
这样的大型向量并且像{{{{}}这样的地图时效率很低1}}。我只是想在第一时间生成我需要的东西,我该怎么做这个工作?
答案 0 :(得分:2)
在您给出的具体示例中,有5,717,712个分区满足这些约束,并且没有约束的可能性更大。因此,组合学效率低下并不是那么重要;我认为你只是低估了有多少可能性。
组合功能是实现您正在寻找的更直接组合的更好工具。
在您的示例中,
(def specific-partitions
(let [initial-list [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17]]
(for [c1 (combinations initial-list 5)
:let [remainder1 (remove (set c1) initial-list)]
c2 (combinations remainder1 6)
:let [remainder2 (remove (set c2) remainder1)]]
[c1 c2 remainder2])))
=>(take 10 specific-partitions)
([(1 2 3 4 5) (6 7 8 9 10 11) (12 13 14 15 16 17)]
[(1 2 3 4 5) (6 7 8 9 10 12) (11 13 14 15 16 17)]
[(1 2 3 4 5) (6 7 8 9 10 13) (11 12 14 15 16 17)]
[(1 2 3 4 5) (6 7 8 9 10 14) (11 12 13 15 16 17)]
[(1 2 3 4 5) (6 7 8 9 10 15) (11 12 13 14 16 17)]
[(1 2 3 4 5) (6 7 8 9 10 16) (11 12 13 14 15 17)]
[(1 2 3 4 5) (6 7 8 9 10 17) (11 12 13 14 15 16)]
[(1 2 3 4 5) (6 7 8 9 11 12) (10 13 14 15 16 17)]
[(1 2 3 4 5) (6 7 8 9 11 13) (10 12 14 15 16 17)]
[(1 2 3 4 5) (6 7 8 9 11 14) (10 12 13 15 16 17)])
它仍然是相当多的分区,但至少你现在正在直接生成它们。
从这个例子中,您可以将此技术概括为一个函数,该函数采用描述分区结构的任意映射,就像您在问题中描述的那样。
如果您的初始集具有重复元素,那么我在此处撰写的特定代码将无法正常工作;这需要稍微不同的删除方法。