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

使用Clojure将集合中的元素分组到新集合中的性能方法,clojure,Clojure,我有一个数万个元素的集合(一个Java列表),我正在编写一个Clojure函数,它需要根据谓词将这个列表分成几个部分。最后,我有几个Clojure集合,其中只有与集合关联的谓词匹配的元素 下面的代码解决了我的问题,但在输入列表上迭代了3次。有更好的方法吗 (defn divide-into-groups [col] (let [one (filter #(< % 3) col) two (filter #(and (>= % 3) (< % 6)) col)

我有一个数万个元素的集合(一个Java列表),我正在编写一个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)]
(定义为分组[col]
(让[1(过滤器#)(<%3)列)
两个(过滤器#(和(>=%3)(<%6))列)
三(过滤器#(>=%6)列)]
[一二三])
(分组(洗牌(范围10)))
;[(2 0 1) (4 3 5) (6 8 7 9)]
我真的在寻找一个功能性的Clojure解决方案。我已经知道我可以创建三个集合作为变量,并在
分组
函数中对它们进行变异,也许这就是Clojure的方法。如果是的话,请说出来


(注意:我上面使用的谓词不是我的生产代码中的谓词。我使用的数据也不是数字。这只是一个SSCCE。这个问题的答案必须适用于集合中任意数据和任意谓词的一般问题。当然,为了清楚起见,还有<代码>过滤器将被完全迭代并用于生成一些输出。因此我不能依赖惰性解决方案;-)

您可以使用
按分区
[1]

(partition-by (fn [x] (cond (< x 3) :coll-1 
                      (and (>= x 3) (< x 6)) :coll-2 
                      (>= x 6) :coll-3)) 
              (range 10))

[1] -

这就是
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]}

是否保证其中一个函数始终为真?是的,其中一个函数始终为真。使用
映射索引
+
一些fn
可以更成功地完成。但我认为这是一个好的解决方案。@Andre,花了一段时间摸索
一些fn
做了什么:)。谢谢你的建议。我已经更新了我的答案。我真的很感谢你们花时间写出这些答案。不幸的是,它们不能解决问题,因为集合没有排序,谓词可能与排序顺序没有任何关系。使用
(随机播放(范围10))
尝试您的解决方案,看看它们是否能产生正确的结果。如果是这样的话,我可以投票表决,否则这不是一个正确的解决方案。
(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]}