-
Notifications
You must be signed in to change notification settings - Fork 0
/
csv.coffee
65 lines (61 loc) · 1.58 KB
/
csv.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
fs = require 'fs'
# custom CSV parser.
#
# each row is returned as a dictionary (keys from first row of CSV file)
#
# if you pass key_field, then this will return a big dictionary (key being the
# value from the row in the key_field column, value being the whole row)
#
# if you pass multiple, then each value in that big dictionary will be an array
# of matching rows
#
# see main.coffee for examples
exports.from_file = (filename, args..., cb) ->
# defaults
delimiter = ','
key_field = null
multiple = false
# (optional) named args
if args.length
args = args[0]
delimiter = args.delimiter if args.delimiter?
key_field = args.key_field if args.key_field?
multiple = args.multiple if args.multiple?
fs.readFile filename, 'utf8', (err, data) ->
return cb err if err?
lines = data.split '\n'
if data.substr(data.length - 1) is '\n'
lines.pop()
keys = lines.shift().split delimiter
if key_field?
ret = {}
else
ret = []
for line in lines
split = line.split delimiter
row = []
parts = []
cur = row
for c in split
if c.length > 1 and c[0] is '"' and c[c.length - 1] is '"'
c = c.substr(1, c.length - 2)
else if c.length > 0 and c[0] is '"'
cur = parts
c = c.substr 1
else if c.length > 1 and c[c.length - 1] is '"'
parts.push c.substr(0, c.length - 1)
c = parts.join(',')
parts = []
cur = row
cur.push c
dict = {}
for k, i in keys
dict[k] = row[i]
if key_field?
if multiple
(ret[dict[key_field]] ?= []).push dict
else
ret[dict[key_field]] = dict
else
ret.push dict
cb null, ret