在Clojure中对地图矢量进行排序和排序的更清洁方法?

时间:2017-12-16 16:51:50

标签: clojure clojurescript

我有一个地图矢量,其中我需要删除名称键值重复的地图,保留具有最高年龄值的地图。我有一个解决方案,但我认为它看起来不干净。有没有更好的方法来做到这一点而不将其分解成多个功能?

这是我的数据:

(def my-maps
    [{:name "jess", :age 32} 
     {:name "ruxpin", :age 4} 
     {:name "jess", :age 35} 
     {:name "aero", :age 33} 
     {:name "banner", :age 4}])

这是我的解决方案:

(map first (vals (group-by :name (reverse (sort-by :name my-maps)))))

结果:

({:name "ruxpin", :age 4} {:name "jess", :age 35} {:name "banner", :age 4} {:name "aero", :age 33})

5 个答案:

答案 0 :(得分:5)

另一种方式是group-bymax-key的组合。这种方法的优点是您不需要对集合进行排序,而sort反过来会对性能产生影响,如果可以避免则应该这样做。

(for [[_ vs] (group-by :name my-maps)]
  (apply max-key :age vs))

;;=> ({:name "jess", :age 35} 
;;    {:name "ruxpin", :age 4} 
;;    {:name "aero", :age 33} 
;;    {:name "banner", :age 4})

答案 1 :(得分:2)

简短版

(->> my-set
     (sort-by (juxt :name :age) #(compare %2 %1)) ; sort-by :name, :age in reverse order
     (partition-by :name)
     (map first))

换能器版本

(def xf (comp (partition-by :name) (map first)))
(->> my-set
     (sort-by (juxt :name :age) #(compare %2 %1))
     (into [] xf))

对于大型数据集,换能器应该更好

答案 2 :(得分:1)

不幸的是,您的原始解决方案实际上已被破坏。它似乎有效,因为你在my-set中有数据的顺序。注意你从未按年龄进行实际排序,因此你无法保证年龄的顺序。

我通过另一次调用map解决了这个问题:

(->> my-set (group-by :name) 
            (vals)

            ; Sort by age each list that group-by returns
            (map #(sort-by :age %)) 

            (map last)) ; This could also happen in the above map

请注意我是如何按:name排序每个:age组,然后我选择每个分组的最后一个。

答案 3 :(得分:0)

我会稍微改变一点,使用max函数而不是排序:

(def my-maps
  [{:name "jess", :age 32}
   {:name "ruxpin", :age 4}
   {:name "jess", :age 35}
   {:name "aero", :age 33}
   {:name "banner", :age 4}])

(dotest
  (let [grouped-data  (group-by :name my-maps)
        name-age-maps (for [[name map-list] grouped-data]
                        (let [max-age      (apply max
                                             (map :age map-list))
                              name-age-map {name max-age}]
                          name-age-map))
        final-result  (reduce into {} name-age-maps)]
    final-result))

结果:

grouped-data => 
{"jess" [{:name "jess", :age 32} {:name "jess", :age 35}],
 "ruxpin" [{:name "ruxpin", :age 4}],
 "aero" [{:name "aero", :age 33}],
 "banner" [{:name "banner", :age 4}]}

name-age-maps => 
({"jess" 35} {"ruxpin" 4} {"aero" 33} {"banner" 4})

final-result => 
{"jess" 35, "ruxpin" 4, "aero" 33, "banner" 4}

答案 4 :(得分:0)

按不同权重和数据类型的向量字段进行比较(大小权重更大),大小为降序,名称为升序:

(def some-vector [{:name "head" :size 3}
                            {:name "mouth" :size 1}
                            {:name "nose" :size 1}
                            {:name "neck" :size 2}
                            {:name "chest" :size 10}
                            {:name "back" :size 10}
                            {:name "abdomen" :size 6}
                            ])
(->> (some-vector)
  (sort #(compare (str (format "%3d" (:size %2)) (:name %1))
                  (str (format "%3d" (:size %1)) (:name %2))
  )))