dictionary - doseq 中的 assoc 字符串导致空映射

标签 dictionary clojure

我正在通过解决问题来学习 Clojure,我陷入困境 with one of them ,基本上我必须在日志文件中找到前五个字符串。

这是我到目前为止所得到的:

(ns topfive
  (:import (java.io BufferedReader FileReader)))


(defn extract-query [line]
  (.substring line (+ (.lastIndexOf line "=") 1) (.lastIndexOf line "]")))

(defn process-file [file-name, queries]
  (with-open [rdr (BufferedReader. (FileReader. file-name))]
    (doseq [line (line-seq rdr)]
      (assoc queries (extract-query line) (inc (get queries (extract-query line) 0))))))

(process-file "in" {})

我的问题是 queries 不包含任何内容,我已经检查过 extract-queries 返回我想要的字符串,我认为这可能有问题与语言本身有关,I've read Clojure 在语言级别具有不变性,但这对我来说仍然不是一个好点。

你能对我做错的事情提出一些建议吗?

最佳答案

Clojure 确实具有低级别的不变性,并且 HashMap 是不可变的。因此,assoc 不会就地改变映射,它会创建一个包含更新项的新映射,并返回新映射。您一遍又一遍地调用 assoc,但丢弃结果。

一个修复方法是使用 reduce 而不是 doseqdoseq 迭代 seq 并对每个项目执行某些操作,但不会累积任何结果。所以它应该主要用于有副作用的事情,例如打印到屏幕或文件。 reduce 类似地迭代 seq,但它确实会累积结果。

(defn process-file [file-name, queries]
  (with-open [rdr (BufferedReader. (FileReader. file-name))]
    (reduce (fn [queries, line]
              (assoc queries (extract-query line) (inc (get queries (extract-query line) 0))))
            queries
            (line-seq rdr))))

您可以做一些事情来进一步简化这一点。 process-file 不需要 queries 参数,因为它一开始总是一个空映射。使用 update-infnil 可以更简洁地编写 assoc 行;这也让我们避免每行调用两次 extract-query 。您可以使用 clojure.java.io 中的 Clojure 包装器 reader 替换对 Java Reader 类的所有调用。您可以用正则表达式替换对 substring 的调用;正则表达式更简洁,但对于大量输入,您的版本可能执行得更快。您还可以使用 #() 将示例中的匿名函数替换为含糖阅读器宏版本,尽管此时它开始看起来有点吵,所以我可能会使用 let 使其读起来更好一点。

(ns topfive
  (:require [clojure.java [io :as io]]))

(defn extract-query [line]
  (nth (re-find #"query=([^]]+)" line) 1))

(defn process-file [file-name]
  (with-open [rdr (io/reader file-name)]
    (reduce #(let [search-term (extract-query %2)]
               (update-in %1 [search-term] (fnil inc 0)))
            {}
            (line-seq rdr))))

关于dictionary - doseq 中的 assoc 字符串导致空映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6418177/

相关文章:

clojure - 确定 Clojure Jar 路径

json - 在clojure中访问POST json

clojure - 在宏中正确处理符号解析

scripting - 使用 Clojure 创建符号链接(symbolic link)

clojure - 在 Clojure 中将 DynamicLabel 转换为 Neo4j 嵌入式标签

Python:使用 mysqldb 将 MySQL 表作为字典导入?

c# - Unity, C#, Dictionary, 计算一场比赛的球队得分

python - 将列表与字典索引进行比较并根据原始列表顺序返回字典值

scala - Scala 2.8.0 和 2.7.7 中 Map 行为的这种令人惊讶的差异(对我来说)是预期的吗?

javascript - 如何在 d3 map 上的鼠标悬停时显示多个值?