(ns net.myexperiments.viciouscycle.util.TSVReader
(:require [clojure.string :as st])
(:import (java.util.regex Pattern) (java.util HashMap) (java.io File))
(:gen-class
:name "net.myexperiments.viciouscycle.util.TSVReader"
:prefix "-"
:load-impl-ns false
:methods [^{:static true} [loadTSV [String] java.util.Map]
^{:static true} [readMap [String] java.util.HashMap]
^{:static true} [convertTSV [String String] String]]))
(defn load-tsv-clj
"Reads a TSV file in and returns a sorted map with the first column's data
as keys, and for values, hashmaps of the header row's data as keys to the
other rows' data as values. A file with a first row of 'Name\tID\tSalary'
and a second row of 'John\t1\t100' will return a sorted map of {\"John\"
{\"Name\" \"John\", \"ID\" 1, \"Salary\" 100}}"
[filename]
(let [tbl-rows (st/split-lines (slurp (File. filename)))
pat-t (. Pattern compile "\t")
header (st/split (first tbl-rows) pat-t)
read-unknown (fn [s] (if (integer? (read-string s)) (read-string s) s))
make-data (fn [rw] (zipmap header (map read-unknown (st/split rw pat-t))))]
(apply sorted-map (interleave
(map (fn [rw] (first (st/split rw pat-t))) (rest tbl-rows))
(map make-data (rest tbl-rows))))))
(defn -loadTSV
"Reads a TSV file in and returns a hash-map with the first column's data
as keys, and for values, hash-maps of the header row's data as keys to the
other rows' data as values. A file with a first row of 'Name\tID\tSalary'
and a second row of 'John\t1\t100' will return a hash-map of {\"John\"
{\"Name\" \"John\", \"ID\" \"1\", \"Salary\" \"100\"}}"
[filename]
(let [tbl-rows (st/split-lines (slurp (File. filename)))
pat-t (. Pattern compile "\t")
header (st/split (first tbl-rows) pat-t)
make-data (fn [rw] (zipmap header (st/split rw pat-t)))]
(apply hash-map (interleave
(map (fn [rw] (first (st/split rw pat-t))) (rest tbl-rows))
(map make-data (rest tbl-rows))))))
(defn read-obj
"Reads a Clojure object from a file, ignoring exceptions."
[filename]
(try
(read-string (slurp (File. filename)))
(catch Exception e nil)))
(defn -readMap
"Reads a Clojure map from a file, returning a Java HashMap
equivalent to the data or an empty HashMap on failure."
[filename]
(try
(let [f (read-string (slurp (File. filename)))]
(if (map? f) (HashMap. f) (HashMap.)))
(catch Exception e (HashMap. ))))
(defn write-obj
"Writes a Clojure object to a file, to be loaded with read-obj ."
[filename obj]
(binding [*out* (java.io.FileWriter. filename)]
(prn obj)))
(defn -convertTSV
"Reads a TSV file (with the name specified by the String infile)
in with loadTSV, using the same format, and writes it to a
Clojure file (with the name specified by the String outfile)."
[infile outfile]
(binding [*out* (java.io.FileWriter. outfile)]
(prn (load-tsv-clj infile))))