使用Clojure将集合中的元素分组到新集合中的高效方法

时间:2015-09-17 15:51:12

标签: clojure

我有一个包含成千上万个元素的集合(Java List),我正在编写一个Clojure函数,需要根据谓词将这个列表拆分成几个部分。最后,我有几个Clojure集合,只有与该集合相关的谓词匹配的元素。

以下代码解决了我的问题,但迭代了输入列表3次。有更好的方法吗?

(defn divide-into-groups [col]
  (let [one (filter #(< % 3) col)
        two (filter #(and (>= % 3) (< % 6)) col)
        three (filter #(>= % 6) col)]
   [one two three]))
(divide-into-groups (shuffle (range 10)))
;[(2 0 1) (4 3 5) (6 8 7 9)]

我真的在寻找功能性的Clojure解决方案。我已经知道我可以创建三个集合作为变量并在divide-into-groups函数内变异它们,也许这就是Clojure方式。如果是的话,请说出来。

(注意:我上面使用的谓词不是我的生产代码中的那些。我使用的数据也不是数字。这只是一个SSCCE。这个问题的答案必须适用于集合和任意谓词中的任意数据的一般问题。当然,性能。要清楚,filter返回的惰性列表将全部迭代并用于生成一些输出。所以我不能依赖懒惰的解决方案; - )

2 个答案:

答案 0 :(得分:2)

这是group-by的用途。除谓词之外,唯一需要的是为每个谓词组指定一个“名称”来指示它将在哪个组中:

(defn divide-into-groups [xs]
  (let [group (fn [x] (cond (>= x 6) :large
                            (>= 6 x 3) :medium
                            :else :small))]
    (group-by group xs)))

user> (divide-into-groups (shuffle (range 10)))
{:small [1 2 0], :large [6 9 8 7], :medium [3 4 5]}

答案 1 :(得分:1)

您可以使用std::array::end [1]。

partition-by

可以从谓词函数序列以编程方式构造所需的函数。唯一值,即(partition-by (fn [x] (cond (< x 3) :coll-1 (and (>= x 3) (< x 6)) :coll-2 (>= x 6) :coll-3)) (range 10)) :coll-1等可以是任何内容,甚至是序列中谓词的索引。

编辑:

:coll-2

[1] - https://clojuredocs.org/clojure.core/partition-by