JavaScript - 如何从 CSV 文件构建层次结构对象
JavaScript - how to build build an hierarchy object from a CSV file
下面有一个 CSV 文件,我想用它构建一个 javascript 对象。
我正在尝试从“类别”列中提取元素并创建层次结构对象,然后将信息放在对象最低级别的“颜色”列下。
目标:
以下是我迄今为止尝试从 CSV 中提取信息的尝试,以及确定如何从这里继续进行的操作。什么是最好最有效的?
let csv = `id, category, year, color, price \n
01, SUV > AWD > Sport > Benz, 2017, blue, \n
02, SUV > FWD > Family > Benz, 2018, black, \n
03, Sedan > AWD > BNW, 2017, white, \n
04, SUV > AWD > Sport > BNW, 2012, red, \n
05, Seden > RWD > Toyota, 2019, white, `
function extractCSV(csv){
let object = {}
let data = csv.split('\n')
for(let i = 1; i < data.length; i++){
let subData = data[i].split(',')
for(let j = 1; j < subData.length; j++){
let header = subData[j].split(">")
if(header.length > 1){
for(let k = 0; k < header.length; k++){
}
}
}
}
return object
}
提前致谢
首先,两个答案中“更好”的那个。
您会发现它遵循与开始时基本相同的流程,但是,我选择将所有解析放在前面,放入一些中间对象中。这允许后面的代码专注于构建我们的树。
let csv = `id, category, year, color, price \n
01, SUV > AWD > Sport > Benz, 2017, blue, \n
02, SUV > FWD > Family > Benz, 2018, black, \n
03, Sedan > AWD > BNW, 2017, white, \n
04, SUV > AWD > Sport > BNW, 2012, red, \n
05, Sedan > RWD > Toyota, 2019, white, `;
function parseCsv(csv) {
let object = {};
// Parse/Sanitize all the data up front
const rows = csv
.split("\n")
.filter((row, index) => index && row)
.map((row) => {
const columns = row.split(",");
return {
headers: columns[1].split(">").map((p) => p.trim()),
color: columns[3].trim()
};
});
// Then spin through the rows
for (const row of rows) {
let currentObj = object;
// Then spin through the headers
for (let hi = 0; hi < row.headers.length; ++hi) {
const header = row.headers[hi];
// If it is the last header, assign the color to it
if (hi === row.headers.length - 1) {
currentObj[header] = row.color;
break;
}
// Else we need to get or set another object level
currentObj = currentObj[header] = currentObj[header] ?? {};
}
}
return object;
}
console.log(parseCsv(csv));
其次,我在这里采用了另一种方法。我发现递归解决方案有些优雅。虽然,它可能更难阅读,很可能会占用更多内存,而且速度更慢,尤其是 document/header 深度增长时。但我把它包括在内是为了好玩!
let csv = `id, category, year, color, price \n
01, SUV > AWD > Sport > Benz, 2017, blue, \n
02, SUV > FWD > Family > Benz, 2018, black, \n
03, Sedan > AWD > BNW, 2017, white, \n
04, SUV > AWD > Sport > BNW, 2012, red, \n
05, Sedan > RWD > Toyota, 2019, white, `;
const parseCsv = (csv) => {
const result = {};
// Parse/Sanitize all the data up front
const rows = csv
.split("\n")
.filter((row, index) => index && row)
.map((row) => {
const columns = row.split(",");
return {
headers: columns[1].split('>').map(p => p.trim()),
color: columns[3].trim()
};
});
// The recursive function, takes in
// {target} the current object in the tree we're at
// {headers} the remaining headers to step through
// {color} the color to assign to the last header
const handleRow = (target, headers, color) => {
// Last header, so just assign the color to it
if (headers.length === 1) {
target[headers[0]] = color;
return;
}
// Else we need to get or set another object level
const newTarget = (target[headers[0]] = target[headers[0]] ?? {});
// And call into the next level with it and the remaining headers
handleRow(newTarget, headers.slice(1), color);
};
for (const row of rows) {
handleRow(result, row.headers, row.color);
}
return result;
};
console.log(parseCsv(csv));
下面有一个 CSV 文件,我想用它构建一个 javascript 对象。
我正在尝试从“类别”列中提取元素并创建层次结构对象,然后将信息放在对象最低级别的“颜色”列下。
目标:
以下是我迄今为止尝试从 CSV 中提取信息的尝试,以及确定如何从这里继续进行的操作。什么是最好最有效的?
let csv = `id, category, year, color, price \n
01, SUV > AWD > Sport > Benz, 2017, blue, \n
02, SUV > FWD > Family > Benz, 2018, black, \n
03, Sedan > AWD > BNW, 2017, white, \n
04, SUV > AWD > Sport > BNW, 2012, red, \n
05, Seden > RWD > Toyota, 2019, white, `
function extractCSV(csv){
let object = {}
let data = csv.split('\n')
for(let i = 1; i < data.length; i++){
let subData = data[i].split(',')
for(let j = 1; j < subData.length; j++){
let header = subData[j].split(">")
if(header.length > 1){
for(let k = 0; k < header.length; k++){
}
}
}
}
return object
}
提前致谢
首先,两个答案中“更好”的那个。
您会发现它遵循与开始时基本相同的流程,但是,我选择将所有解析放在前面,放入一些中间对象中。这允许后面的代码专注于构建我们的树。
let csv = `id, category, year, color, price \n
01, SUV > AWD > Sport > Benz, 2017, blue, \n
02, SUV > FWD > Family > Benz, 2018, black, \n
03, Sedan > AWD > BNW, 2017, white, \n
04, SUV > AWD > Sport > BNW, 2012, red, \n
05, Sedan > RWD > Toyota, 2019, white, `;
function parseCsv(csv) {
let object = {};
// Parse/Sanitize all the data up front
const rows = csv
.split("\n")
.filter((row, index) => index && row)
.map((row) => {
const columns = row.split(",");
return {
headers: columns[1].split(">").map((p) => p.trim()),
color: columns[3].trim()
};
});
// Then spin through the rows
for (const row of rows) {
let currentObj = object;
// Then spin through the headers
for (let hi = 0; hi < row.headers.length; ++hi) {
const header = row.headers[hi];
// If it is the last header, assign the color to it
if (hi === row.headers.length - 1) {
currentObj[header] = row.color;
break;
}
// Else we need to get or set another object level
currentObj = currentObj[header] = currentObj[header] ?? {};
}
}
return object;
}
console.log(parseCsv(csv));
其次,我在这里采用了另一种方法。我发现递归解决方案有些优雅。虽然,它可能更难阅读,很可能会占用更多内存,而且速度更慢,尤其是 document/header 深度增长时。但我把它包括在内是为了好玩!
let csv = `id, category, year, color, price \n
01, SUV > AWD > Sport > Benz, 2017, blue, \n
02, SUV > FWD > Family > Benz, 2018, black, \n
03, Sedan > AWD > BNW, 2017, white, \n
04, SUV > AWD > Sport > BNW, 2012, red, \n
05, Sedan > RWD > Toyota, 2019, white, `;
const parseCsv = (csv) => {
const result = {};
// Parse/Sanitize all the data up front
const rows = csv
.split("\n")
.filter((row, index) => index && row)
.map((row) => {
const columns = row.split(",");
return {
headers: columns[1].split('>').map(p => p.trim()),
color: columns[3].trim()
};
});
// The recursive function, takes in
// {target} the current object in the tree we're at
// {headers} the remaining headers to step through
// {color} the color to assign to the last header
const handleRow = (target, headers, color) => {
// Last header, so just assign the color to it
if (headers.length === 1) {
target[headers[0]] = color;
return;
}
// Else we need to get or set another object level
const newTarget = (target[headers[0]] = target[headers[0]] ?? {});
// And call into the next level with it and the remaining headers
handleRow(newTarget, headers.slice(1), color);
};
for (const row of rows) {
handleRow(result, row.headers, row.color);
}
return result;
};
console.log(parseCsv(csv));