【问题标题】:Clojure reduce functionClojure减少功能
【发布时间】:2018-10-29 18:43:24
【问题描述】:

我正在尝试从 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 `frequencies` function.)

我不明白这部分:(inc (%1 %2 0))

【问题讨论】:

    标签: clojure


    【解决方案1】:

    传递给reduce 的函数的第一个参数(匿名函数中的%1)是累加器,它最初是作为第二个参数传递给reduce 的空映射{}。 Maps 是查找给定键值的函数,如果找不到键,则返回可选的默认值,例如

    ({"word" 1} "word") = 1
    

    ({"word" 1} "other" 0) = 0
    

    所以

    (%1 %2 0)
    

    在累加器映射中查找当前单词(归约函数的第二个参数)的计数,如果尚未添加该单词,则返回 0。 inc 增加当前计数,所以

    #(assoc %1 %2 (inc (%1 %2 0))
    

    增加中间映射中当前单词的计数,如果这是第一次遇到该单词,则将其设置为 1。

    【讨论】:

      【解决方案2】:

      这是一个更易于阅读的相同内容示例,不使用匿名函数语法:

      (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))

      1. inc 将增加从内部表达式返回的数字
      2. (acc elem 0) 将从 acc 映射到单词 elem 的当前数字 get,如果那里没有数字,它将返回 0。这是(get acc elem 0) 的缩写——映射也是函数,其行为类似于get 函数。

      你也可以用(update acc elem (fnil inc 0))达到和(assoc acc elem (inc (acc elem 0)))一样的效果。

      当您使用带编号参数的匿名语法替换 reduce 函数时,同样的逻辑也适用。

      【讨论】:

        【解决方案3】:

        您所询问的代码本质上是 that of the standard frequencies function 并删除了 transients

        (defn frequencies [coll]
           (reduce
             (fn [counts x] (assoc counts x (inc (get counts x 0))))
             {}
             coll))
        

        这个

        【讨论】:

          猜你喜欢
          • 2020-03-25
          • 2014-09-26
          • 2016-03-26
          • 2020-11-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-02
          相关资源
          最近更新 更多