Reducing The Reduction

I need to compare specific columns in two csv files. Clojure fits the bill.

But the reports (csv files) containing the information I want contain many more columns of information than I need or want to store. clojure-csv is great at parsing csv files. and Clojure’s reduce is great at pulling apart the clojure-csv resulting vector of vectors.

But I want to pull select columns out of each vector. What if I do not want to hard-code the indexes, but supply the index in a collection? In that way, I could vary the length of the subset vector and the columns without relying on hard-coded length (the number of indexes) or column values.

I can think of some other ways to have done the filter, but reduce seemed the logical choice.


(ns bene-csv.core
^{:author "Charles M. Norton",
:doc "bene-csv is a small library to parse a .csv file.
Created on March 8, 2012"}
(:gen-class)
(:require [clojure.string :as cstr])
(:use clojure-csv.core))

(def cols-select [1 3 5 9])

(defn ret-csv-file
"Returns a lazy sequence generated by parse-csv.
Does not try to do anything fancy."

[fnam]
(let [  csv-data (slurp fnam)
csv-file (parse-csv csv-data)]
csv-file))

(defn reduce-csv-row
"Accepts a csv-row and a column, and extracts it."
[csv-row col-nums]
(reduce
(fn [out-csv-row col-num]
(let [out-val (nth csv-row col-num nil)]
(if-not (nil? out-val)
(conj out-csv-row out-val))))
[]
col-nums))

(defn out-csv
"Accepts a lazy-seq parsed by ret-csv-file and returns a smaller file that
was reduced by the cols-select argument."

[all-csv-rows cols-select]
(reduce
(fn [out-csv-rows one-csv-row]
(let [reduced-row (reduce-csv-row one-csv-row cols-select)]
(conj out-csv-rows reduced-row)))
[]
all-csv-rows))

"main added for temporary testing"

(defn -main
[& args]
(let [csv-rows (ret-csv-file "test.csv")]
(let [ret-rows (out-csv csv-rows cols-select)]
(println (subvec ret-rows 0 (- (count ret-rows) 0))))))

Advertisements

Leave a comment

Filed under Clojure

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s