d3-dsv
此模組提供分隔符號值的剖析器和格式化程式,最常見的是 逗號分隔值 (CSV) 或 tab 分隔值 (TSV)。這些表格格式在 Microsoft Excel 等試算表程式中很受歡迎,而且通常比 JSON 更節省空間。此實作基於 RFC 4180。
例如,要剖析
d3.csvParse("foo,bar\n1,2") // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]
d3.tsvParse("foo\tbar\n1\t2") // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]
要格式化
d3.csvFormat([{foo: "1", bar: "2"}]) // "foo,bar\n1,2"
d3.tsvFormat([{foo: "1", bar: "2"}]) // "foo\tbar\n1\t2"
要使用不同的分隔符號,例如直線分隔值的「|」,請使用 d3.dsvFormat
d3.dsvFormat("|").parse("foo|bar\n1|2")) // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]
若要輕鬆載入瀏覽器中的 DSV 檔案,請參閱 d3-fetch 的 d3.csv、d3.tsv 和 d3.dsv 方法。
dsvFormat(delimiter)
const csv = d3.dsvFormat(",");
原始碼 · 建立新的 DSV 解析器和格式化器,用於指定的分隔符。分隔符必須是單一字元(即,單一 16 位元碼元);因此,ASCII 分隔符是可以的,但表情符號分隔符不行。
dsv.parse(字串, 列)
注意
此方法需要不安全的 eval 內容安全性政策。
d3.csvParse("foo,bar\n1,2") // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]
原始碼 · 解析指定的字串,該字串必須採用分隔符分隔值格式,並使用適當的分隔符,傳回一個陣列的物件,代表已解析的列。
與 dsv.parseRows 不同,此方法要求 DSV 內容的第一行包含分隔符分隔的欄位名稱清單;這些欄位名稱會成為傳回物件的屬性。例如,考慮以下 CSV 檔案
Year,Make,Model,Length
1997,Ford,E350,2.34
2000,Mercury,Cougar,2.38
產生的 JavaScript 陣列為
[
{"Year": "1997", "Make": "Ford", "Model": "E350", "Length": "2.34"},
{"Year": "2000", "Make": "Mercury", "Model": "Cougar", "Length": "2.38"}
]
傳回的陣列也會公開一個 columns
屬性,其中包含輸入順序的欄位名稱(與 Object.keys 不同,後者的迭代順序是任意的)。例如
data.columns // ["Year", "Make", "Model", "Length"]
如果欄位名稱不唯一,只會傳回每個名稱的最後一個值;若要存取所有值,請改用 dsv.parseRows(請參閱 範例)。
如果未指定列轉換函式,欄位值會是字串。為了安全,不會自動轉換為數字、日期或其他類型。在某些情況下,JavaScript 可能自動將字串強制轉換為數字(例如,使用 +
算子),但最好指定一個列轉換函式。請參閱 d3.autoType,取得一個方便的列轉換函式,用於推論和強制轉換常見類型,例如數字和字串。
如果指定了列轉換函式,則會針對每一列呼叫指定的函式,並傳遞一個代表目前列的物件(d
)、從第一個非標頭列開始的索引(i
)以及欄位名稱陣列。如果傳回值為 null 或 undefined,則會略過該列,並從 dsv.parse 傳回的陣列中省略;否則,傳回值會定義對應的列物件。例如
const data = d3.csvParse(string, (d) => {
return {
year: new Date(+d.Year, 0, 1), // lowercase and convert "Year" to Date
make: d.Make, // lowercase
model: d.Model, // lowercase
length: +d.Length // lowercase and convert "Length" to number
};
});
注意:通常使用 +
或 Number
而不是 parseInt 或 parseFloat 會比較快,但限制也比較多。例如,使用 +
轉換 "30px"
會傳回 NaN
,而 parseInt 和 parseFloat 會傳回 30
。
dsv.parseRows(字串, 列)
d3.csvParseRows("foo,bar\n1,2") // [["foo", "bar"], ["1", "2"]]
原始碼 · 分析指定的 字串,該字串必須採用分隔符值格式,並使用適當的分隔符,傳回一個陣列,其中包含代表已分析列的陣列。
與 dsv.parse 不同,此方法將標題列視為標準列,並且應在 DSV 內容不包含標題時使用。每列都表示為陣列,而不是物件。列的長度可能不同。例如,考慮以下 CSV 檔案,特別的是它沒有標題列
1997,Ford,E350,2.34
2000,Mercury,Cougar,2.38
產生的 JavaScript 陣列為
[
["1997", "Ford", "E350", "2.34"],
["2000", "Mercury", "Cougar", "2.38"]
]
如果未指定列轉換函式,欄位值會是字串。為了安全,不會自動轉換為數字、日期或其他類型。在某些情況下,JavaScript 可能自動將字串強制轉換為數字(例如,使用 +
算子),但最好指定一個列轉換函式。請參閱 d3.autoType,取得一個方便的列轉換函式,用於推論和強制轉換常見類型,例如數字和字串。
如果指定 列 轉換函式,則會針對每一列呼叫指定的函式,並傳入代表目前列的陣列 (d
)、從第一列開始的索引 (i
) 和欄位名稱陣列。如果傳回值為 null 或未定義,則會略過該列,且不會包含在 dsv.parse 傳回的陣列中;否則,傳回值會定義對應的列物件。例如
const data = d3.csvParseRows(string, (d, i) => {
return {
year: new Date(+d[0], 0, 1), // convert first column to Date
make: d[1],
model: d[2],
length: +d[3] // convert fourth column to number
};
});
實際上,列 類似於將 map 和 filter 算子套用至傳回的列。
dsv.format(列, 欄位)
d3.csvFormat([{foo: "1", bar: "2"}]) // "foo,bar\n1,2"
d3.csvFormat([{foo: "1", bar: "2"}], ["foo"]) // "foo\n1"
原始碼 · 將指定的物件 列 陣列格式化為分隔符值,傳回字串。此操作是 dsv.parse 的反向操作。每一列會以換行符號 (\n
) 分隔,且每一列中的每一欄位會以分隔符 (例如逗號 ,
) 分隔。包含分隔符、雙引號 ("
) 或換行符號的值會使用雙引號進行跳脫。
如果未指定 欄位,則會透過判斷 列 中所有物件的所有屬性的聯集來決定形成標題列的欄位名稱清單;欄位的順序是不確定的。如果指定 欄位,則它是一個代表欄位名稱的字串陣列。例如
const string = d3.csvFormat(data, ["year", "make", "model", "length"]);
每一列物件中的所有欄位都會強制轉換為字串。如果欄位值為 null 或未定義,則會使用空字串。如果欄位值為日期,則會使用 ECMAScript 日期時間字串格式 (ISO 8601 的子集):例如,UTC 子夜的日期會格式化為 YYYY-MM-DD
。若要進一步控制格式化哪些欄位以及如何格式化,請先將 列 對應到字串陣列陣列,然後使用 dsv.formatRows。
dsv.formatBody(rows, columns)
d3.csvFormatBody([{foo: "1", bar: "2"}]) // "1,2"
d3.csvFormatBody([{foo: "1", bar: "2"}], ["foo"]) // "1"
來源 · 等同於 dsv.format,但會省略標題列。這在某些情況下很有用,例如將列新增到現有檔案時。
dsv.formatRows(rows)
d3.csvFormatRows([["foo", "bar"], ["1", "2"]]) // "foo,bar\n1,2"
來源 · 將指定的字串陣列 rows 格式化為分隔符號值,並傳回字串。此操作與 dsv.parseRows 相反。每一列都會以換行符號 (\n
) 分隔,而每一列中的每個欄位都會以分隔符號 (例如逗號 ,
) 分隔。包含分隔符號、雙引號 (") 或換行符號的值會使用雙引號進行跳脫。
若要將物件陣列轉換為陣列陣列,同時明確指定欄位,請使用 array.map。例如
const string = d3.csvFormatRows(data.map((d, i) => {
return [
d.year.getUTCFullYear(), // Assuming d.year is a Date object.
d.make,
d.model,
d.length
];
}));
如果您願意,也可以使用 array.concat 將此結果與欄位名稱陣列合併,以產生第一列
const string = d3.csvFormatRows([[
"year",
"make",
"model",
"length"
]].concat(data.map((d, i) => {
return [
d.year.getUTCFullYear(), // Assuming d.year is a Date object.
d.make,
d.model,
d.length
];
})));
dsv.formatRow(row)
d3.csvFormatRow(["foo", "bar"]) // "foo,bar"
來源 · 將單一字串陣列 row 格式化為分隔符號值,並傳回字串。每一列中的每個欄位都會以分隔符號 (例如逗號 ,
) 分隔。包含分隔符號、雙引號 (") 或換行符號的值會使用雙引號進行跳脫。
dsv.formatValue(value)
d3.csvFormatValue("foo") // "foo"
來源 · 將單一 value 或字串格式化為分隔符號值,並傳回字串。包含分隔符號、雙引號 (") 或換行符號的值會使用雙引號進行跳脫。
csvParse(string, row)
csvParseRows(string, row)
等同於 d3.dsvFormat(",").parseRows
。
csvFormat(rows, columns)
csvFormatBody(rows, columns)
等同於 d3.dsvFormat(",").formatBody
。
csvFormatRows(rows)
等同於 d3.dsvFormat(",").formatRows
。
csvFormatRow(row)
等同於 d3.dsvFormat(",").formatRow
。
csvFormatValue(value)
等同於 d3.dsvFormat(",").formatValue
。
tsvParse(string, row)
tsvParseRows(string, row)
等同於 d3.dsvFormat("\t").parseRows
。
tsvFormat(rows, columns)
等同於 d3.dsvFormat("\t").format
。
tsvFormatBody(rows, columns)
等同於 d3.dsvFormat("\t").formatBody
。
tsvFormatRows(rows)
等同於 d3.dsvFormat("\t").formatRows
。
tsvFormatRow(row)
等同於 d3.dsvFormat("\t").formatRow
。
tsvFormatValue(value)
等同於 d3.dsvFormat("\t").formatValue
。
autoType(object)
原始碼 · 給定一個表示已剖析列的物件(或陣列),推論物件上值的類型並強制轉換它們,傳回已變異的物件。此函式預計與 dsv.parse 和 dsv.parseRows 搭配使用,作為列存取函式。例如,考慮以下 CSV 檔案
Year,Make,Model,Length
1997,Ford,E350,2.34
2000,Mercury,Cougar,2.38
當與 d3.csvParse 搭配使用時,
d3.csvParse(string, d3.autoType)
產生的 JavaScript 陣列為
[
{"Year": 1997, "Make": "Ford", "Model": "E350", "Length": 2.34},
{"Year": 2000, "Make": "Mercury", "Model": "Cougar", "Length": 2.38}
]
類型推論的工作方式如下。對於給定物件中的每個值,會計算已修剪的值;然後重新指派值如下
- 如果為空,則為
null
。 - 如果完全為
"true"
,則為true
。 - 如果完全為
"false"
,則為false
。 - 如果完全為
"NaN"
,則為NaN
。 - 否則,如果可強制轉換為數字,則為數字。
- 否則,如果為僅日期或日期時間字串,則為日期。
- 否則,為字串(原始未修剪的值)。
具有前導零的值可能會強制轉換為數字;例如,"08904"
強制轉換為8904
。但是,額外的字元,例如逗號或單位(例如,"$1.00"
、"(123)"
、"1,234"
或"32px"
)將會阻止數字強制轉換,導致字串。
日期字串必須採用 ECMAScript 的ISO 8601 格式子集。當指定僅日期字串,例如 YYYY-MM-DD 時,推論時間為 UTC 午夜;但是,如果指定日期時間字串,例如 YYYY-MM-DDTHH:MM,且沒有時區,則假設為當地時間。
自動類型推論主要用於提供安全的可預測行為,並與dsv.format和dsv.formatRows結合使用,以適用於常見的 JavaScript 類型。如果您需要不同的行為,則應實作您自己的列存取函數。
更多資訊,請參閱d3.autoType 筆記本。
內容安全政策
如果已設定內容安全政策,請注意dsv.parse需要在script-src
指令中設定unsafe-eval
,因為為了快速解析而(安全地)使用動態程式碼產生。(請參閱原始碼。)或者,使用dsv.parseRows。
位元組順序標記
DSV 檔案有時會以 位元組順序標記 (BOM) 開頭;例如,從 Microsoft Excel 以 CSV UTF-8 格式儲存試算表會包含 BOM。在網路上這通常不是問題,因為編碼標準中指定的 UTF-8 解碼演算法 會移除 BOM。另一方面,Node.js 在解碼 UTF-8 時 不會移除 BOM。
如果未移除 BOM,文字的第一個字元會是零寬度不換行空白。因此,如果 d3.csvParse 分析帶有 BOM 的 CSV 檔案,第一欄的名稱會以零寬度不換行空白開頭。這可能很難發現,因為這個字元在列印時通常是看不見的。
若要在分析前移除 BOM,請考慮使用 strip-bom。