代码之家  ›  专栏  ›  技术社区  ›  frank

使用clojure data.csv从单个输入行流式处理多个输出行

  •  0
  • frank  · 技术社区  · 8 年前

    我正在读取csv文件,处理输入,将输出附加到输入,并将结果写入输出csv看起来很直截了当。我在用 clojure数据.csv 是的。然而,我在输出中遇到了一个细微差别,它与我以前在Clojure中遇到的任何东西都不匹配,我无法理解输出将为每个输入包含0到N行,我不知道如何将其流下到调用fn。

    以下是正在处理文件的表单:

    (defn process-file
      [from to]
      (let [ctr (atom 0)]
        (with-open [r (io/reader from)
                    w (io/writer to)]
          (some->> (csv/read-csv r)
                   (map #(process-line % ctr))
                   (csv/write-csv w)))))
    

    下面是处理每一行的表单(返回0到n行,每行需要写入输出csv):

    (defn process-line
      [line ctr]
      (swap! ctr inc)
      (->> (apps-for-org (first line))
           (reduce #(conj %1 (add-results-to-input line %2)) [])))
    
    2 回复  |  直到 8 年前
        1
  •  2
  •   Carcigenicate    8 年前

    老实说,我不完全理解你的问题,但从你的评论来看,我似乎已经回答了。

    如果你想跑 csv/write-csv 对于返回的每一行,您只需映射这些行:

    (some->> (csv/read-csv r)
             (map #(process-line % ctr)) 
             (mapv #(csv/write-csv w %))))
    

    注意我使用的 mapv 因为你有副作用根据上下文,如果您使用 map ,懒惰可以阻止写作的发生。

    可以说,使用 doseq 然而:

    (let [rows (some->> (csv/read-csv r)
                        (map #(process-line % ctr)))]
    
      (doseq [row rows] 
        (csv/write-csv w row)))
    

    剂量 明确说明迭代的目的是执行副作用,而不是生成新的(不可变的)列表。

        2
  •  1
  •   Taylor Wood    8 年前

    我想你遇到的问题是 map 功能 process-line 返回从零到多行的集合,因此 地图 当您只想将一个集合(行)发送到 write-csv 是的。如果这是真的,那么修复方法只是将这一行改为使用 mapcat :

    (mapcat #(process-line % ctr))
    

    地图猫 就像 地图 ,但它将“合并”每个 生产线 调用一个集合。

    推荐文章