Small script to help process data from a CSV file. Messaround with promises also.
First part of script is just helpers- skip to Start Filtering to see the body.
fs = require 'fs'
_ = require 'underscore'
Q = require 'q'
StreamSplitter = require 'stream-splitter'Given a string line, will generate object from csv.
extractRow = (str) ->
datum = _.object [
'noSearches', 'hr', 'dy', 'mn', 'yr', 'time'
], str.split ','Given the data csv file, returns a promise that is resolved with an array of records.
readData = (file = './data.csv') ->
ds = fs
.createReadStream(file, flags: 'r')
.pipe StreamSplitter '\n'
ds.encoding = 'utf8'
ds.on 'token', (buf) ->
records.push\
( ( buf .split('\n')
.filter (line) -> not /^\s*$/.test line
.map extractRow )... )
ds.on 'done', -> def.resolve records
ds.on 'error', (e) -> def.reject e
# Create an array for the data records
records = []
(def = Q.defer()).promiseReads a line from stdin.
readline = (msg) ->
process.stdout.write msg if msg?
process.stdin.resume()
process.stdin.setEncoding 'utf8'
process.stdin.once 'data', (data) ->
def.resolve data.trim()
(def = Q.defer()).promiseWrapper around readline to take accept.
yn = ->
readline.apply arguments
.then (res) ->
ys = /^(?:1|t(?:rue)?|y(?:es)?|ok(?:ay)?)$/i
if not ys.test res
throw Error 'User declined'
else resProduces a function that generates an array filter method, which will filter all duplicate elements from an array of records given equality on the configured key (default 'time').
filterDuplicates = (key = 'time') -> (records) ->
kv = {}
kv[v[key]] = v for v in records
return _.values kvOutputs readable records
printRecords = (records) ->
console.log records
console.log """\n
Found #{records.length} records in the supplied data.\n"""
return recordsConverts an array of records to CSV string.
csvify = (records) ->
_.keys(records[0]).join(',') +
records.reduce ((a,r) -> "#{a}\n#{_.values(r).join ','}"), ''Offers user chance to write new csv file, returning write promise.
offerCsv = (records) ->
yn readline 'Would you like to write a new CSV file? '
.then -> readline '\nPlease enter filename: '
.then (file = './output.csv') ->
console.log "Writing to #{file}..."
Q.nfcall fs.writeFile, file, csvify(records), 'utf8'
.then -> console.log 'Done!\n'
.catch (err) -> truereadData()
.then filterDuplicates 'time'
.then printRecords
.then offerCsv
.catch (err) -> console.log err
.finally (err) -> console.log 'Exiting.'; process.exit 0
.done()