File Clojure懒洋洋地从文件中读取随机行

File Clojure懒洋洋地从文件中读取随机行,file,asynchronous,clojure,lazy-sequences,File,Asynchronous,Clojure,Lazy Sequences,我有一个txt文件中的示例数据集。数据文件非常大,因此无法将其加载到内存中。我需要能够懒洋洋地阅读文件。此外,我需要以随机顺序读取这些行。可能有些情况下我不需要读所有的台词。这就是我目前发现的- (defn read-lazy [in-file] (letfn [(helper [rdr] (if-let [line (.readLine rdr)] (cons

我有一个txt文件中的示例数据集。数据文件非常大,因此无法将其加载到内存中。我需要能够懒洋洋地阅读文件。此外,我需要以随机顺序读取这些行。可能有些情况下我不需要读所有的台词。这就是我目前发现的-

(defn read-lazy [in-file]
        (letfn [(helper [rdr]
                            (if-let [line (.readLine rdr)]
                                (cons line (helper rdr))
                                (do (.close rdr) nil)))]
            (helper (io/reader in-file))))
它返回文件的惰性seq。当我需要时,如何在惰性序列中的随机行中循环?我想用围棋可以帮上忙。Go块可以在通道中放置一条随机线,并等待有东西消耗它。一旦数据被读取,它会在通道中放置另一行,等待下一次读取。我如何实现这一点

以下是我是如何计算出来的(不是随机的)-

(def lazy ch(chan))
(defn异步获取集[在文件中]
(去
(打开[读卡器(io/文件中的读卡器)]
(doseq[行(行顺序读卡器)]
(>!懒ch行)))
(关闭!懒惰的人)
(println“got:”(

这是解决问题的好方法吗?有更好的解决方案吗?我可能不需要阅读所有的行,因此我希望能够在需要时关闭读卡器。

您上面的解决方案不包括任何随机性。Go通道是先进先出的结构。如果您确实想要随机读取,您首先需要计算文件中的行数,然后使用
(rand N)
生成间隔[0..N-1]内的整数
I
,然后从文件中读取行
I

从文件中读取行
I
有几种不同的方法,它们权衡了速度和内存需求

(defn char-seq
  "Returns a lazy sequence of characters from rdr. rdr must implement
  java.io.Reader."
  [rdr]
  (let [c (.read rdr)]
    (if-not (neg? c)
      (cons (char c) (lazy-seq (char-seq rdr))))))

(defn line-offsets
  "Returns a lazy sequence of offsets of all lines in s."
  [s]
  (if (seq s)
    (->> (partition-all 3 1 s)
         (map-indexed
          (fn [i [a b c]]
            (cond
              (= b \newline) (if c (+ 2 i))
              (= a \return) (if b (inc i)))))
         (filter identity)
         (cons 0))))

(defn ordered-line-seq
  "Returns the lines of text from raf at each offset in offsets as a lazy
  sequence of strings. raf must implement java.io.RandomAccessFile."
  [raf offsets]
  (map (fn [i]
         (.seek raf i)
         (.readLine raf))
       offsets))
用法示例:

(let [filename "data.txt"
      offsets (with-open [rdr (clojure.java.io/reader filename)]
                (shuffle (line-offsets (char-seq rdr))))]
  (with-open [raf (java.io.RandomAccessFile. filename "r")]
    (dorun (map println (ordered-line-seq raf offsets)))))

所以,为了确保我正确理解您的问题:您需要按顺序对文件的每一行执行相同的操作,但顺序必须是随机的?是的。这就是我要做的。我添加了一个更新
(let [filename "data.txt"
      offsets (with-open [rdr (clojure.java.io/reader filename)]
                (shuffle (line-offsets (char-seq rdr))))]
  (with-open [raf (java.io.RandomAccessFile. filename "r")]
    (dorun (map println (ordered-line-seq raf offsets)))))