如何使用(主要)数组方法从 2 个相应的项目创建一个合并项目的数组,每个项目来自另一个附加数组?



我已经将基于 CSV 的文本文件转换为包含标题和行的数组,现在我想将它们转换为下面给出的解决方案。任何人都可以使用mapreduce或其他方法做到这一点吗?

我拥有的数组是:

let header = ['a', 'b', 'c', 'd'];
let rows = ['1,2,3,4', '5,6,7,8', '9,0,1,2'];

我想要的结果是:

[{
a: 1,
b: 2,
c: 3,
d: 4,
}, {
a: 5,
b: 6,
c: 7,
d: 8,
}, {
a: 9,
b: 0,
c: 1,
d: 2,
}]

我能够使用 for 循环来做到这一点,但这不是 es6 的合适解决方案。

上面我提到了一些虚拟数组,现在实际的代码是:

const recordReader = content => {
let weatherRecords = [];
let rows = content.split('n');
let headers = rows.shift().split(',');
for (let row = 0; row < rows.length; row++) {
let weatherReading = {};
if (!rows[row]) {
continue;
}
let record = rows[row].split(',');

for (let column = 0; column < headers.length; column++) {
weatherReading[headers[column]] = record[column];
}
weatherRecords.push(weatherReading);
}
return weatherRecords;
};

您可以映射行并将行缩减为对象:

const header = ['a', 'b', 'c', 'd'];
const rows = ['1,2,3,4', '5,6,7,8', '9,0,1,2'];
const result = rows.map((row) =>
row.split(',').reduce(
(obj, cell, i) => ({
...obj,
[header[i]]: Number(cell),
}),
{}
)
);
console.log(result)

map和reduce的组合:

const header = ['a', 'b', 'c', 'd'];
const rows = ['1,2,3,4', '5,6,7,8', '9,0,1,2'];
const res = rows.map(row => {
const columns = row.split(',');
return columns.reduce( (acc,cur,i) => ({...acc,[header[i]]:cur}) , {})
}
);
console.log(res);

这承认一行,但我认为不是很清楚它的作用:

const header = ['a', 'b', 'c', 'd'];
const rows = ['1,2,3,4', '5,6,7,8', '9,0,1,2'];
const res = rows.map(row => row.split(',').reduce( (acc,cur,i) => ({...acc,[header[i]]:cur}) , {}));
console.log(res);

您可以将rows元素.map()到对象。要创建对象,您可以获取数字字符串,并将它们拆分为一个数组,然后使用.map()该数组从headers中获取数字值和关联的标头,使用当前数字的索引 (i)。通过将它们放入[key, value]对数组中,您可以在其上调用Object.fromEntries()来构建对象。下面还使用一元加号运算符 (+) 将字符串数字转换为数字:

const header = ['a', 'b', 'c', 'd'];
const rows = ['1,2,3,4', '5,6,7,8', '9,0,1,2'];
const res = rows.map(item =>
Object.fromEntries(item.split(',').map((n, i) => [header[i], +n]))
);
console.log(res);

注意,上面用的Object.fromEntries()是在 ES6 之后引入的,你可以用Object.assign()来做一个微笑的方法,也就是 ES6:

const header = ['a', 'b', 'c', 'd'];
const rows = ['1,2,3,4', '5,6,7,8', '9,0,1,2'];
const res = rows.map(item =>
Object.assign({}, ...item.split(',').map((n, i) => ({[header[i]]: +n})))
);
console.log(res);

试试这段代码

let header = ['a', 'b', 'c', 'd'];
let rows = ['1,2,3,4', '5,6,7,8', '9,0,1,2'];
let result = rows.map((x) => {
let elementArr = x.split(',');
let response = [];
header.forEach((item,i) => {
response[item] = parseInt(elementArr[i])
});

return {...response};
});
console.log(result)

试试这个

let header = ['a', 'b', 'c', 'd'];
let rows = ['1,2,3,4', '5,6,7,8', '9,0,1,2'];
result=[]
rows.forEach(e=>{
let a={};
let i=0;
header.forEach((h)=>{
a[h]=e.split(',')[i++]
});
result.push(a)
});

基于嵌套reduce的方法就可以完成这项工作。

一个使用外部化简函数迭代rows数组,该函数再次通过第二个reduce任务迭代每个列值(派生自每个splittedrow),该任务将列值分配给列键,其中每个键都派生自额外传递的header数组和当前内部迭代的列索引。

function rowwiseAssignColumValuesToHeaderColumnKeys({ header, result }, row) {
result
.push(
row
.split(',')
.reduce((rowItem, columnValue, columnIndex) =>
Object.assign(rowItem, {
[ header[columnIndex] ]: Number(columnValue.trim())
}), {} // to be aggregated `rowItem` passed as initial value.
)
);
return { header, result };
}
console.log(
['1,2,3,4', '5, 6, 7, 8', '9,0,1,2']
.reduce(
rowwiseAssignColumValuesToHeaderColumnKeys, {
header: ['a', 'b', 'c', 'd'],
result: [],
},
).result
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

上述主要基于reduce的方法可以重构为可重用的映射函数,该函数考虑了Array.prototype.map的第二个thisArg参数

function assignColumValuesAccordingToBoundHeaderColumnKeys(row) {
const header = this;
return  row
.split(',')
.reduce((rowItem, columnValue, columnIndex) =>
Object.assign(rowItem, {
[ header[columnIndex] ]: Number(columnValue.trim())
}), {} // to be aggregated `rowItem` passed as initial value.
);
}
console.log(
['1,2,3,4', '5, 6, 7, 8', '9,0,1,2']
.map(
assignColumValuesAccordingToBoundHeaderColumnKeys,
['a', 'b', 'c', 'd'],
)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

最新更新