使用带有clojure的过滤器计算文件中的行

时间:2016-04-18 11:39:37

标签: clojure

我正试图弄清楚我的代码出了什么问题。基本上它背后的想法是我正在读取一个非常大的文件,并且在文件中每行的末尾是一个数字。我想计算末尾数字大于500的行数。

我所拥有的就是这个,而且在纸面上它应该有用,但是出了点问题,我一直都没错。

(defn countlines [] (with-open [rdr (clojure.java.io/reader "myfile.txt")]
(doseq [line (line-seq rdr)]
(count (re-find #"(?!500)[56789]\d{2,}|\d{4,}$" line)))))

3 个答案:

答案 0 :(得分:4)

原因是您使用doseq

clojure.core / doseq  [seq-exprs&身体] 宏 在1.0中添加   反复执行身体(可能是副作用)   绑定和过滤由“for”提供。不保留   序列的头部。 返回nil。

您应该将其重写为类似(doall (for [line (line-seq rdr)] ...

的内容

但要完成你的任务,你需要重写它(因为你的函数会在匹配中返回一系列字符数:

user> (count (re-find #"\d+" "123k456"))
3

这显然不是你想要的

您需要做的是:

(count (filter #(re-find #"(?!500)[56789]\d{2,}|\d{4,}$" %)
               (line-seq rdr)))

答案 1 :(得分:1)

如果我正确理解了这个问题,你应该这样做:

(defn countlines [] (with-open [rdr (clojure.java.io/reader "myfile.txt")]
(-> (line-seq rdr)
    (filter #(re-find #"(?!500)[56789]\d{2,}|\d{4,}$" %))
    (count))))

答案 2 :(得分:0)

关于Martin Lechner的回答,我认为应该使用Thread last( - >>)而不是Thread first( - >)。所以它应该是

(defn countlines [] (with-open [rdr (clojure.java.io/reader "myfile.txt")] (->> (line-seq rdr)
(filter #(re-find #"(?!500)[56789]\d{2,}|\d{4,}$" %))
(count))))