diff --git a/README.md b/README.md index 50eeda2..6187017 100644 --- a/README.md +++ b/README.md @@ -43,43 +43,51 @@ var data = d3.csvParse(string); ## API Reference -# d3.csvParse(string[, row]) [<>](https://github.com/d3/d3-dsv/blob/master/src/csv.js#L5 "Source") +# d3.csvParse(string[, row]) [<>](https://github.com/d3/d3-dsv/blob/master/src/csv.js "Source") Equivalent to [dsvFormat](#dsvFormat)(",").[parse](#dsv_parse). -# d3.csvParseRows(string[, row]) [<>](https://github.com/d3/d3-dsv/blob/master/src/csv.js#L6 "Source") +# d3.csvParseRows(string[, row]) [<>](https://github.com/d3/d3-dsv/blob/master/src/csv.js "Source") Equivalent to [dsvFormat](#dsvFormat)(",").[parseRows](#dsv_parseRows). -# d3.csvFormat(rows[, columns]) [<>](https://github.com/d3/d3-dsv/blob/master/src/csv.js#L7 "Source") +# d3.csvFormat(rows[, columns]) [<>](https://github.com/d3/d3-dsv/blob/master/src/csv.js "Source") Equivalent to [dsvFormat](#dsvFormat)(",").[format](#dsv_format). -# d3.csvFormatRows(rows) [<>](https://github.com/d3/d3-dsv/blob/master/src/csv.js#L8 "Source") +# d3.csvFormatBody(rows[, columns]) [<>](https://github.com/d3/d3-dsv/blob/master/src/csv.js "Source") + +Equivalent to [dsvFormat](#dsvFormat)(",").[formatBody](#dsv_formatBody). + +# d3.csvFormatRows(rows) [<>](https://github.com/d3/d3-dsv/blob/master/src/csv.js "Source") Equivalent to [dsvFormat](#dsvFormat)(",").[formatRows](#dsv_formatRows). -# d3.tsvParse(string[, row]) [<>](https://github.com/d3/d3-dsv/blob/master/src/tsv.js#L5 "Source") +# d3.tsvParse(string[, row]) [<>](https://github.com/d3/d3-dsv/blob/master/src/tsv.js "Source") Equivalent to [dsvFormat](#dsvFormat)("\t").[parse](#dsv_parse). -# d3.tsvParseRows(string[, row]) [<>](https://github.com/d3/d3-dsv/blob/master/src/tsv.js#L6 "Source") +# d3.tsvParseRows(string[, row]) [<>](https://github.com/d3/d3-dsv/blob/master/src/tsv.js "Source") Equivalent to [dsvFormat](#dsvFormat)("\t").[parseRows](#dsv_parseRows). -# d3.tsvFormat(rows[, columns]) [<>](https://github.com/d3/d3-dsv/blob/master/src/tsv.js#L7 "Source") +# d3.tsvFormat(rows[, columns]) [<>](https://github.com/d3/d3-dsv/blob/master/src/tsv.js "Source") Equivalent to [dsvFormat](#dsvFormat)("\t").[format](#dsv_format). -# d3.tsvFormatRows(rows) [<>](https://github.com/d3/d3-dsv/blob/master/src/tsv.js#L8 "Source") +# d3.tsvFormatBody(rows[, columns]) [<>](https://github.com/d3/d3-dsv/blob/master/src/tsv.js "Source") + +Equivalent to [dsvFormat](#dsvFormat)("\t").[formatBody](#dsv_formatBody). + +# d3.tsvFormatRows(rows) [<>](https://github.com/d3/d3-dsv/blob/master/src/tsv.js "Source") Equivalent to [dsvFormat](#dsvFormat)("\t").[formatRows](#dsv_formatRows). -# d3.dsvFormat(delimiter) [<>](https://github.com/d3/d3-dsv/blob/master/src/dsv.js#L30) +# d3.dsvFormat(delimiter) [<>](https://github.com/d3/d3-dsv/blob/master/src/dsv.js) Constructs a new DSV parser and formatter for the specified *delimiter*. The *delimiter* must be a single character (*i.e.*, a single 16-bit code unit); so, ASCII delimiters are fine, but emoji delimiters are not. -# *dsv*.parse(string[, row]) [<>](https://github.com/d3/d3-dsv/blob/master/src/dsv.js#L34 "Source") +# *dsv*.parse(string[, row]) [<>](https://github.com/d3/d3-dsv/blob/master/src/dsv.js "Source") Parses the specified *string*, which must be in the delimiter-separated values format with the appropriate delimiter, returning an array of objects representing the parsed rows. @@ -123,7 +131,7 @@ var data = d3.csvParse(string, function(d) { Note: using `+` rather than [parseInt](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/parseInt) or [parseFloat](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/parseFloat) is typically faster, though more restrictive. For example, `"30px"` when coerced using `+` returns `NaN`, while parseInt and parseFloat return `30`. -# dsv.parseRows(string[, row]) [<>](https://github.com/d3/d3-dsv/blob/master/src/dsv.js#L43 "Source") +# dsv.parseRows(string[, row]) [<>](https://github.com/d3/d3-dsv/blob/master/src/dsv.js "Source") Parses the specified *string*, which must be in the delimiter-separated values format with the appropriate delimiter, returning an array of arrays representing the parsed rows. @@ -160,7 +168,7 @@ var data = d3.csvParseRows(string, function(d, i) { In effect, *row* is similar to applying a [map](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map) and [filter](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter) operator to the returned rows. -# dsv.format(rows[, columns]) [<>](https://github.com/d3/d3-dsv/blob/master/src/dsv.js#L105 "Source") +# dsv.format(rows[, columns]) [<>](https://github.com/d3/d3-dsv/blob/master/src/dsv.js "Source") Formats the specified array of object *rows* as delimiter-separated values, returning a string. This operation is the inverse of [*dsv*.parse](#dsv_parse). Each row will be separated by a newline (`\n`), and each column within each row will be separated by the delimiter (such as a comma, `,`). Values that contain either the delimiter, a double-quote (`"`) or a newline will be escaped using double-quotes. @@ -172,7 +180,11 @@ var string = d3.csvFormat(data, ["year", "make", "model", "length"]); All fields on each row object will be coerced to strings. If the field value is null or undefined, the empty string is used. If the field value is a Date, the ISO 8601 date format is used per [*date*.toISOString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString). For more control over which and how fields are formatted, first map *rows* to an array of array of string, and then use [*dsv*.formatRows](#dsv_formatRows). -# dsv.formatRows(rows) [<>](https://github.com/d3/d3-dsv/blob/master/src/dsv.js#L114 "Source") +# dsv.formatBody(rows[, columns]) [<>](https://github.com/d3/d3-dsv/blob/master/src/dsv.js "Source") + +Equivalent to [*dsv*.format](#dsv_format), but omits the header row. This is useful, for example, when appending rows to an existing file. + +# dsv.formatRows(rows) [<>](https://github.com/d3/d3-dsv/blob/master/src/dsv.js "Source") Formats the specified array of array of string *rows* as delimiter-separated values, returning a string. This operation is the reverse of [*dsv*.parseRows](#dsv_parseRows). Each row will be separated by a newline (`\n`), and each column within each row will be separated by the delimiter (such as a comma, `,`). Values that contain either the delimiter, a double-quote (") or a newline will be escaped using double-quotes. diff --git a/src/csv.js b/src/csv.js index b85be9c..aa9144a 100644 --- a/src/csv.js +++ b/src/csv.js @@ -5,4 +5,5 @@ var csv = dsv(","); export var csvParse = csv.parse; export var csvParseRows = csv.parseRows; export var csvFormat = csv.format; +export var csvFormatBody = csv.formatBody; export var csvFormatRows = csv.formatRows; diff --git a/src/dsv.js b/src/dsv.js index 99f0d14..8aba35c 100644 --- a/src/dsv.js +++ b/src/dsv.js @@ -95,13 +95,22 @@ export default function(delimiter) { return rows; } - function format(rows, columns) { - if (columns == null) columns = inferColumns(rows); - return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) { + function preformatBody(rows, columns) { + return rows.map(function(row) { return columns.map(function(column) { return formatValue(row[column]); }).join(delimiter); - })).join("\n"); + }); + } + + function format(rows, columns) { + if (columns == null) columns = inferColumns(rows); + return [columns.map(formatValue).join(delimiter)].concat(preformatBody(rows, columns)).join("\n"); + } + + function formatBody(rows, columns) { + if (columns == null) columns = inferColumns(rows); + return preformatBody(rows, columns).join("\n"); } function formatRows(rows) { @@ -123,6 +132,7 @@ export default function(delimiter) { parse: parse, parseRows: parseRows, format: format, + formatBody: formatBody, formatRows: formatRows }; } diff --git a/src/index.js b/src/index.js index 0473f32..b3053b9 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,4 @@ export {default as dsvFormat} from "./dsv"; -export {csvParse, csvParseRows, csvFormat, csvFormatRows} from "./csv"; -export {tsvParse, tsvParseRows, tsvFormat, tsvFormatRows} from "./tsv"; +export {csvParse, csvParseRows, csvFormat, csvFormatBody, csvFormatRows} from "./csv"; +export {tsvParse, tsvParseRows, tsvFormat, tsvFormatBody, tsvFormatRows} from "./tsv"; export {default as autoType} from "./autoType"; diff --git a/src/tsv.js b/src/tsv.js index 5e8b363..9fe418a 100644 --- a/src/tsv.js +++ b/src/tsv.js @@ -5,4 +5,5 @@ var tsv = dsv("\t"); export var tsvParse = tsv.parse; export var tsvParseRows = tsv.parseRows; export var tsvFormat = tsv.format; +export var tsvFormatBody = tsv.formatBody; export var tsvFormatRows = tsv.formatRows; diff --git a/test/csv-test.js b/test/csv-test.js index d97180f..9d70ecb 100644 --- a/test/csv-test.js +++ b/test/csv-test.js @@ -299,6 +299,16 @@ tape("csvFormat(array, columns) coerces field values to strings", function(test) test.end(); }); +tape("csvFormatBody(array) omits the header row", function(test) { + test.deepEqual(dsv.csvFormatBody([{a: 1, b: 2}, {c: 3, b: 4}, {c: 5, a: 1, b: 2}]), "1,2,\n,4,3\n1,2,5"); + test.end(); +}); + +tape("csvFormatBody(array, columns) omits the header row", function(test) { + test.deepEqual(dsv.csvFormatBody([{a: 1, b: 2}, {c: 3, b: 4}, {c: 5, a: 1, b: 2}], ["a", "b"]), "1,2\n,4\n1,2"); + test.end(); +}); + tape("csvFormatRows(array) takes an array of array of string as input", function(test) { test.deepEqual(dsv.csvFormatRows([["a", "b", "c"], ["1", "2", "3"]]), "a,b,c\n1,2,3"); test.end();