我需要编写一个函数,根据字段的值将记录拆分为单独的文件。例如。给定输入:维护多个打开的文件(Clojure)
[
["Paul" "Smith" 35]
["Jason" "Nielsen" 39]
["Charles" "Brown" 22]
]
我们结束了一个文件"Paul"
,含"Paul Smith 35"
,文件"Jason"
,含"Jason Nielsen 39"
等
我不知道事先的名字,所以我需要保持引用对于作家来说,我最后可以关闭它们。
我能想出用一个裁判保持的作家,像这样的最好的:
(defn write-split [records]
(let [out-dir (io/file "/tmp/test/")
open-files (ref {})]
(try
(.mkdirs out-dir)
(dorun
(for [[fst lst age :as rec] records]
(binding [*out* (or
(@open-files fst)
(dosync
(alter open-files assoc fst (io/writer (str out-dir "/" fst)))
(@open-files fst)))]
(println (apply str (interpose " " rec))))))
(finally (dorun (map #(.close %) (vals @open-files)))))))
这工作,但感觉太可怕了,更重要的是,用完堆的,即使只有我有五个输出文件,一开始就打开。似乎有东西被保留在某种程度上......
任何人都可以想到一个更实用和类似Clojure的解决方案吗?
编辑:输入很大。有可能是千兆字节的数据,因此内存效率的重要性,以及每次写入后都不愿意关闭文件。
记录数据如此之大,您无法将其分组在内存中?'(group-by first records)',然后在返回的地图中为每个新键打开和关闭一个文件。 – ponzao 2012-01-05 12:50:15
是的,这是很大的 - 通过一个懒惰的序列进入数据的千兆字节。理想情况下, – George 2012-01-05 13:34:51
是否有要求保持文件打开状态,还是需要打开有限的文件总数?大多数操作系统只允许一定数量的打开文件。 – deterb 2012-01-05 13:51:06