Clojure简单马尔可夫数据变换

标签 clojure hashmap markov

如果我有一个单词向量,例如 [“john”“said”...“john”“walked”...] 我想制作每个单词的 HashMap 以及下一个单词出现的次数,例如 {"john"{"said"1 "walked"1 "kicked"3}}

我想出的最好的解决方案是按索引递归地遍历列表并使用 assoc 来不断更新 HashMap ,但这看起来真的很困惑。有更惯用的方法吗?

最佳答案

既然你有话:

(def words ["john" "said" "lara" "chased" "john" "walked" "lara" "chased"])

使用这个转换-fn

(defn transform
  [words]
  (->> words
       (partition 2 1)
       (reduce (fn [acc [w next-w]]
                 ;; could be shortened to #(update-in %1 %2 (fnil inc 0))
                 (update-in acc
                            [w next-w]
                            (fnil inc 0))) 
               {})))

(transform words)
;; {"walked" {"lara" 1}, "chased" {"john" 1}, "lara" {"chased" 2}, "said" {"lara" 1}, "john" {"walked" 1, "said" 1}}

编辑:您可以使用 transient HashMap 来提高性能,如下所示:

(defn transform-fast
  [words]
  (->> (map vector words (next words))
       (reduce (fn [acc [w1 w2]]
                 (let [c-map (get acc w1 (transient {}))]
                   (assoc! acc w1 (assoc! c-map w2
                                          (inc (get c-map w2 0))))))
               (transient {}))
       persistent!
       (reduce-kv (fn [acc w1 c-map]
                    (assoc! acc w1 (persistent! c-map)))
                  (transient {}))
       persistent!))

显然,生成的源代码看起来不太好,并且只有在至关重要时才应进行此类优化。

(Criterium 表示它击败了 Michał Marczyks transform*,其速度大约是《李尔王》的两倍)。

关于Clojure简单马尔可夫数据变换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20203883/

相关文章:

clojure - "No single method [...] found for function"尝试使用协议(protocol)

clojure - 映射中键和值的顺序

dictionary - 除了 map 和矢量之外,get 在 Clojure 中还有其他用途吗?

javascript - 马尔可夫聚类算法

clojure - 在累加器上进行归约和映射会产生堆栈溢出

java - 如何读取文本文件并使用 HashMap 存储?

Java HashMap 内部

具有 Factory 的 Java 库

algorithm - Markov Decision Process : value iteration, 它是如何工作的?

machine-learning - 使用神经网络进行强化学习