Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 从大文件中惰性地提取行_Clojure_Lazy Evaluation_Stream Processing - Fatal编程技术网

Clojure 从大文件中惰性地提取行

Clojure 从大文件中惰性地提取行,clojure,lazy-evaluation,stream-processing,Clojure,Lazy Evaluation,Stream Processing,我试图通过Clojure从一个大(>1GB)文件中获取5行的行号。我就快到了,但看到了一些奇怪的事情,我想知道发生了什么 到目前为止,我已经: (defn multi-nth [values indices] (map (partial nth values) indices)) (defn read-lines [file indices] (with-open [rdr (clojure.java.io/reader file)] (let [lines (line-seq

我试图通过Clojure从一个大(>1GB)文件中获取5行的行号。我就快到了,但看到了一些奇怪的事情,我想知道发生了什么

到目前为止,我已经:

(defn multi-nth [values indices]
  (map (partial nth values) indices))

(defn read-lines [file indices]
  (with-open [rdr (clojure.java.io/reader file)]
    (let [lines (line-seq rdr)]
      (multi-nth lines indices))))
现在,
(读取行“我的文件”[0])
可以正常工作。但是,传入
[01]
会给我以下堆栈跟踪:

java.lang.RuntimeException: java.io.IOException: Stream closed
        Util.java:165 clojure.lang.Util.runtimeException
      LazySeq.java:51 clojure.lang.LazySeq.sval
      LazySeq.java:60 clojure.lang.LazySeq.seq
         Cons.java:39 clojure.lang.Cons.next
          RT.java:769 clojure.lang.RT.nthFrom
          RT.java:742 clojure.lang.RT.nth
         core.clj:832 clojure.core/nth
         AFn.java:163 clojure.lang.AFn.applyToHelper
         AFn.java:151 clojure.lang.AFn.applyTo
         core.clj:602 clojure.core/apply
        core.clj:2341 clojure.core/partial[fn]
      RestFn.java:408 clojure.lang.RestFn.invoke
        core.clj:2430 clojure.core/map[fn]
在我可以从文件中读取第二行之前,流似乎已经关闭。有趣的是,如果我用
(第n行200)
之类的东西手动从文件中拉出一行,
多个第n行
调用适用于所有值map(和line seq)返回惰性序列,因此在调用open returns时不必读取任何行,这将关闭文件

基本上,在使用open returns之前,您需要实现整个返回值,您可以使用doall:

(defn multi-nth [values indices]
  (map (partial nth values) indices))

(defn read-lines [file indices]
  (with-open [rdr (clojure.java.io/reader file)]
    (let [lines (line-seq rdr)]
      (doall (multi-nth lines indices)))))
或者类似的。请记住,在搜索指定的行时,multi-nth会保留seq行的开头,这意味着它将保留所有行,直到内存中最后一个指定的行为止——像这样使用nth意味着您要为每个索引重复遍历seq行——您需要修复这一点

更新:

像这样的东西会有用的。这比我喜欢的要难看一点,但它显示了一个原则,我认为:注意这里的索引需要是一个

(defn multi-nth [values indices]
 (keep 
   (fn [[number line]] 
     (if (contains? indices number) 
       line))
   (map-indexed vector values)))

(multi-nth '(a b c d e) #{2 3})
  => c d

with file
在执行文件正文后关闭文件。因此,一旦执行了
multi-nth
,文件就会关闭,这意味着您将得到一个指向已关闭文件的惰性序列

(读取行“我的文件”[0])
工作,因为只有惰性序列的第一个元素被实现

要解决此问题,需要使用
doall
强制实现序列:

(defn multi-nth [values indices]
  (doall (map (partial nth values) indices)))

有关详细说明,请参见

好的观点。我是否需要使用较低级别的Java随机访问方法调用来获得正确的结果?我认为使用映射索引和过滤器可以获得相当清晰的代码。我马上更新……啊,好的,太好了。如果它的语法比您想要的更难看,您可以使用keep-indexed并可能压缩过滤器函数。现在调查一下。。。