我正在尝试在节点中将一个非常大的 json 转换为 csv.js但这花费了太多时间,并且在转换时也会导致 100% CPU。
jsonToCsv: function (data) {
var keys = Object.keys(data[0]);
var csv = [keys.join(",")];
console.time("CSVGeneration");
data.forEach(function (row) {
var line = '';
keys.forEach(function (key) {
if (typeof row[key] === 'string') {
row[key] = "" + file_utils.escapeCsv(row[key]) + "";
}
line += row[key] + ",";
});
csv.push(line);
});
console.timeEnd("CSVGeneration");
csv = csv.join("n");
return csv;
},
escapeCsv: function (x) {
if (x)
return ('' + x.replace(/"/g, '').replace(/,/g, ' ').replace(/n/g, " ").replace(/r/g, " ") + '');
else
return ('');
},
在平均运行 1Lac 行时,它从未恢复到甚至日志时间。我不得不手动终止该过程。
有人可以提出更好的替代方案吗?
在回答这个问题之前: 假设你的代码正在工作,这个问题属于 https://codereview.stackexchange.com/。
至于你的问题:
- 新的数组访问功能,如
forEach()
,虽然在编码时相当舒适,但通常性能不高。在性能关键情况下,简单的for
循环是更好的选择。 - 在
escapeCsv()
中,您可以应用4个不同的正则表达式替换,每个替换仅针对一个字符。将它们合二为一。 - 假设您的数据已经以一种允许 Csv 转换的方式结构化(
data
是一个对象数组,每个对象都具有相同的属性(,没有必要为每个对象单独检索键。
应用此方法,将生成以下代码:
function escapeCsv(x) {
if (x) {
return ('' + x).replace( /[",nr]/gi, '' );
} else {
return ('');
}
}
function jsonToCsv(data) {
var keys = Object.keys(data[0]),
csv = [keys.join(",")];
var row = new Array( keys.length );
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < keys.length; j++) {
if (typeof data[i][keys[j]] === 'string') {
row[j] = '"' + escapeCsv(data[i][keys[j]]) + '"';
} else {
row[j] = data[i][keys[j]] || '';
}
}
csv.push(row.join(','));
}
return csv.join("n");
}
根据 jsPerf,仅此一项就产生了大约 3-5 个性能改进。
如果您正在生成的CSV可以直接流式传输到文件或客户端,则可以进一步改进并减少内存负载,因为CSV不必存储在内存中。
摆弄功能,以玩转功能 原来像你的一样命名,新的名字带有后缀 2
.
jsPerf.com 比较