Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vector 计算自定义clojure向量中的重复项_Vector_Clojure - Fatal编程技术网

Vector 计算自定义clojure向量中的重复项

Vector 计算自定义clojure向量中的重复项,vector,clojure,Vector,Clojure,我试图提出一个函数式解决方案来解释由交替集合和数值组成的自定义数据结构中的重复项 例如: (def a [#{:a} 0.1 #{:b} 0.3 #{:a :b} 0.1 #{:a} 0.3 #{:b} 0.1 #{:a} 0.1]) 我想添加与重复集对应的值,以生成 [#{:a} 0.5 #{:b} 0.4 #{:a :b} 0.1] 我可以使用loop/recur实现这一点,但我想知道是否有一种方法可以在Clojure中使用高阶函数 谢谢。我会将源向量折叠成一张地图,其中的键用作数值的聚

我试图提出一个函数式解决方案来解释由交替集合和数值组成的自定义数据结构中的重复项

例如:

(def a [#{:a} 0.1 #{:b} 0.3 #{:a :b} 0.1 #{:a} 0.3 #{:b} 0.1 #{:a} 0.1])
我想添加与重复集对应的值,以生成

[#{:a} 0.5 #{:b} 0.4 #{:a :b} 0.1]
我可以使用
loop/recur
实现这一点,但我想知道是否有一种方法可以在Clojure中使用高阶函数


谢谢。

我会将源向量折叠成一张地图,其中的键用作数值的聚合,然后将其展开成向量

(->> a
     (partition 2)
     (reduce (fn [acc [k v]]
               (if (get acc k)
                 (update acc k (partial + v))
                 (assoc acc k v)))
             {})
     (reduce (fn [acc [k v]]
               (into acc [k v]))
             []))
首先,使用
partition
将序列划分为键值对,然后使用
reduce
将这些键值对进行划分。诀窍是使用
fnil
,它将取代
nil
,用于尚未添加到
acc
但值为
0
的密钥

这会给你一张地图:

{#{:a} 0.5, #{:b} 0.4, #{:b :a} 0.1}
如果需要将其作为值的平面序列,可以通过
seq
flant
传递:

(->> a
  (partition 2)
  (reduce
    (fn [acc [k v]]
      (update acc k (fnil + 0) v))
    {})
  (apply concat)
  (into []))

;; => (#{:a} 0.5 #{:b} 0.4 #{:b :a} 0.1)
还有一个变体(只是为了好玩,因为
reduce
version显然有更好的性能):


你能分享你的循环/重现解决方案吗?对的顺序重要吗?如果没有,您可以将数据保存为从一组关键字到数字序列(向量?)的映射。我以前从未使用过
fnil
。谢谢你指出这一点。非常优雅。不客气:)。我忽略了你需要的是一系列的值,而不是一张地图。我已经更新了我的答案。我知道我没有将你的答案标记为“已接受”,但确实如此。但愿我能把两者都标为已接受。我做了一个
(into[](seq(flatten)))
来得到最后的向量。
展平
通常是个坏主意。在这种情况下(只有一个深度级别),最好使用
(apply concat)
(mapcat identity)
而不是
(flatte)
。它还可以让您删除
(seq)
来自的行there@leetwinski你说得对,让我加强我的回答。
(->> a
  (partition 2)
  (reduce
    (fn [acc [k v]]
      (update acc k (fnil + 0) v))
    {})
  (apply concat)
  (into []))

;; => (#{:a} 0.5 #{:b} 0.4 #{:b :a} 0.1)
(->> a
     (partition 2)
     (group-by first)
     (map (fn [[k v]] [k (apply + (map second v))]))
     (reduce into []))