Clojure归约函数
我试图从clojuredocs.org了解此功能:Clojure归约函数,clojure,Clojure,我试图从clojuredocs.org了解此功能: ;; Create a word frequency map out of a large string s. ;; `s` is a long string containing a lot of words :) (reduce #(assoc %1 %2 (inc (%1 %2 0))) {} (re-seq #"\w+" s)) ; (This can also be done using the `frequenc
;; Create a word frequency map out of a large string s.
;; `s` is a long string containing a lot of words :)
(reduce #(assoc %1 %2 (inc (%1 %2 0)))
{}
(re-seq #"\w+" s))
; (This can also be done using the `frequencies` function.)
我不理解这部分:(inc(%1%2 0))传递给reduce
的函数的第一个参数(%1
)是累加器,它最初是作为第二个参数传递给reduce
的空映射。映射是查找给定键的值的函数,如果找不到键,则返回可选的默认值,例如
({"word" 1} "word") = 1
及
所以
在累加器映射中查找当前单词(reduce函数的第二个参数)的计数,如果尚未添加单词,则返回0inc
增加当前计数,因此
#(assoc %1 %2 (inc (%1 %2 0))
增加中间映射中当前单词的计数,如果这是第一次遇到该单词,则将其设置为1。下面是一个简单易懂的示例,不使用匿名函数语法:
(reduce
(fn [acc elem]
(assoc acc elem (inc (acc elem 0))))
{}
(re-seq #"\w+" "a dog a cat a dog a banana"))
=> {"a" 4, "dog" 2, "cat" 1, "banana" 1}
这里的acc
是我们正在构建的地图,elem
是当前的单词。让我们分解一下(inc(acc elem 0))
:
inc
将递增从内部表达式返回的数字(acc elem 0)
将从acc
地图中获取elem
单词的当前编号,如果没有编号,则返回0
。这是(get acc elem 0)
——映射也是函数,其行为类似于get
函数(更新acc elem(fnil inc 0))
实现与(assoc acc elem(inc(acc elem 0))相同的效果
当您使用使用编号参数的匿名语法替换reduce函数时,同样的逻辑也适用。您询问的代码基本上是删除的:
这个
- 使用
fn
表单而不是
)及
- 包括一个多余的,这给了我们一个默认的线索
0
值
#(assoc %1 %2 (inc (%1 %2 0))
(reduce
(fn [acc elem]
(assoc acc elem (inc (acc elem 0))))
{}
(re-seq #"\w+" "a dog a cat a dog a banana"))
=> {"a" 4, "dog" 2, "cat" 1, "banana" 1}
(defn frequencies [coll]
(reduce
(fn [counts x] (assoc counts x (inc (get counts x 0))))
{}
coll))