Clojure 地图的最高 3 个值

Clojure highest 3 values of a map

嗨,我正在尝试做一个函数,return是 3 个最常见的字符串

  (take 3 (sort-by val > (frequencies s))))

(freq ["hi" "hi" "hi" "ola" "hello" "hello" "string" "str" "ola" "hello" "hello" "str"])

到目前为止我已经知道了,但是我注意到如果有超过 1 个字符串具有相同的频率,它就不会 return。有没有办法根据频率函数的最高值(最终是前 3 最高值)过滤频率函数的值?

提前致谢。

frequencies 给你一张地图,其中的键是原始值 调查并且该地图中的值是那些频率 值。对于您的结果,您对 all 原始值感兴趣, 出现次数最多的,包括那些原始值 相同的事件。

一种方法是“反转”频率结果,从中获取地图 与该事件一起出现的所有原始值。那么你就可以 获得最高的 N 个键并从这张地图和 select 他们(通过使用 用于反转地图的“排序地图”,我们可以通过键进行排序而无需 进一步的步骤)。

(defn invert-map
  ([source]
   (invert-map source {}))
  ([source target]
   (reduce (fn [m [k v]]
             (update m v (fnil conj []) k))
           target
           source)))

(assert (=
         {1 ["do" "re"]}
         (invert-map {"do" 1 "re" 1})))

(defn freq
  [n s]
  (let [fs (invert-map (frequencies s) (sorted-map-by >))
        top-keys (take n (keys fs))]
    (select-keys fs top-keys)))

(assert (=
         {4 ["hello"], 3 ["hi"], 2 ["ola" "str"]}
         (freq 3 ["hi" "hi" "hi" "ola" "hello" "hello" "string" "str" "ola" "hello" "hello" "str"])))

我会提出略有不同的解决方案,其中涉及使用 group-by 值(即项目计数)反转频率图:

(->> data
     frequencies
     (group-by val))

;;{3 [["hi" 3]],
;; 2 [["ola" 2] ["str" 2]],
;; 4 [["hello" 4]],
;; 1 [["string" 1]]}

所以您唯一需要做的就是对其进行排序和处理:

(->> data
     frequencies
     (group-by val)
     (sort-by key >)
     (take 3)
     (mapv (fn [[k vs]] {:count k :items (mapv first vs)})))

;;[{:count 4, :items ["hello"]}
;; {:count 3, :items ["hi"]}
;; {:count 2, :items ["ola" "str"]}]