遍历嵌套数组并转换为对象
Looping through nested arrays and converting to objects
我想使用从嵌套数组中收集的信息将一组嵌套数组转换为对象数组:
之前:
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
之后:
[
{firstName: 'Bob', lastName: 'Lob', age: 22, role: 'salesperson'},
{firstName: 'Mary', lastName: 'Joe', age: 32, role: 'director'}
]
这是我为解决这个问题而编写的函数,但我不太明白循环哪里出了问题:
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
for (var y = 0; y < employeeData[i][y].length; y++) {
newObject[employeeData[i][y][0]] = employeeData[i][y][1];
}
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
提前致谢。
如何修复代码
你只需要 2 个 for 循环:
1.迭代数组
2. 迭代子数组并构造对象
var employeeData = [[["firstName","Bob"],["lastName","Lob"],["age",22],["role","salesperson"]],[["firstName","Mary"],["lastName","Joe"],["age",32],["role","director"]]]
function transformData(employeeData) {
let newObject;
const newArr = [];
for (var i = 0; i < employeeData.length; i++) {
newObject = {}; // init new object
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1]; // iterate inner arrays and assign properties to object
}
newArr.push(newObject);
}
return newArr;
}
console.log(transformData(employeeData));
另一种选择是使用 Array#map to iterate the outer array and Array#reduce 的组合从内部数组构造一个对象:
const employeeData = [[["firstName","Bob"],["lastName","Lob"],["age",22],["role","salesperson"]],[["firstName","Mary"],["lastName","Joe"],["age",32],["role","director"]]]
const result = employeeData.map((arr) =>
arr.reduce((o, [key, value]) => (o[key] = value, o), {})
);
console.log(result);
你的代码有什么问题:
第三级for
循环搞砸了。它应该被删除:
for (var y = 0; y < employeeData[i][x].length; y++) {
// ^ by the way this should be x not y (not fixing the problem though)
因为第三级数组包含 2 个您需要同时使用的元素(作为键值),应该删除它们的 for
循环.
修复:
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1];
}
newArr.push(newObject);
newObject = {};
}
固定代码示例:
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1];
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
备选方案:
您可以将 map
employeeData
数组转换成一个新数组,reduce
将每个子数组转换成一个对象,如下所示:
var result = employeeData.map(function(sub) {
return sub.reduce(function(obj, pair) {
obj[ pair[0] ] = pair[1];
return obj;
}, {});
});
可以使用 ES6 的箭头函数将其缩短为:
let result = employeeData.map(sub => sub.reduce((obj, pair) => (obj[pair[0]] = pair[1], obj), {}));
示例:
let employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
];
let result = employeeData.map(sub => sub.reduce((obj, pair) => (obj[pair[0]] = pair[1], obj), {}));
console.log(result);
您可能只想对外部数组中的每组值使用 Map
而不是 Object
。
那么就是new Map(data);
的一个很简单的转换了。地图已添加到此类数据集的规范中。
var employeeData = [
[['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']],
[['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']]
];
const res = employeeData.map(a => new Map(a));
for (const m of res) {
console.log(m.get("firstName"));
}
但是如果你最终想要数组中的 Object
类型,那么你可以转换每个 Map()
.
var employeeData = [
[['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']],
[['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']]
];
const res = employeeData.map(a => new Map(a));
for (const m of res) {
console.log(m.get("firstName"));
}
const oRes = res.map(m => Object.assign({}, ...Array.from(m.entries()).map(([k,v]) => ({[k]:v}))));
console.log(oRes);
问题出在您对变量 x 和 y 的使用
一方面,这条线
for (var y = 0; y < employeeData[i][y].length; y++)
也许您的意思是改用 employeeData[i][x].length
,因为在您这里,它的行为会很奇怪。
但是,如果将变量 y
替换为 x
(在您的实现中甚至从未使用过)
,则可以完全消除变量
这是我对您的函数的修改建议:
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1];
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
运行 你的示例进行了这些更改后我得到了正确的输出:
[
{
firstName: 'Bob',
lastName: 'Lob',
age: 22,
role: 'salesperson'
},
{
firstName: 'Mary',
lastName: 'Joe',
age: 32,
role: 'director'
}
]
其他人已经指出 map
数组函数的使用如何可以简化您的任务,这些都是很好的解决方案(比计算循环要好得多),但它们没有解决您实际提出的问题。
您的代码实际上工作得很好,只是您没有提取所有可用的数据。你只有名字和姓氏。通过再添加两行,您可以获得其余数据。此外,甚至不需要第二个循环(它不会伤害您,但实际上并没有帮助,因为您从不在任何地方使用 x
计数器)。
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var y = 0; y < employeeData[i][y].length; y++) {
newObject[employeeData[i][y][0]] = employeeData[i][y][1];
// Now you have to get the next two array elements as well:
newObject[employeeData[i][y+1][0]] = employeeData[i][y+1][1];
newObject[employeeData[i][y+2][0]] = employeeData[i][y+2][1];
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
如果您正确使用索引,可以像您尝试的那样使用 for 循环解决您面临的问题。
如果你像我一样格式化你的数据,你会看到你的索引有三个级别你的 [i,x,y];
例如,对于 employeeData[0],您应该得到:
[
['firstName', 'Bob'],
['lastName', 'Lob'],
['age', 22],
['role', 'salesperson']
]
然后对于 employeeData[0][0] 你应该得到:
['firstName', 'Bob']
对于 employeeData[0][0][0] 你应该得到:'firstName'
要访问 'Bob',您需要访问 employeeData[0][0][1],因为您知道这个内部数组中只有两个元素,所以您不需要遍历它。
正如@TallChuck 所建议的,你的问题很大一部分源于忘记使用你的 x 索引。
var employeeData = [
[
['firstName', 'Bob'],
['lastName', 'Lob'],
['age', 22],
['role', 'salesperson']
],
[
['firstName', 'Mary'],
['lastName', 'Joe'],
['age', 32],
['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1];
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
编辑
如果你注意你的索引,你也可以做一些更复杂的解决方案。假设您有以下数据:
var employeeData = [
[
['firstName', 'Bob', 'weight', '80kg'],
['lastName', 'Lob'],
['age', 22],
['role', 'salesperson']
],
[
['firstName', 'Mary', 'eye color', 'green'],
['lastName', 'Joe'],
['age', 32],
['role', 'director']
]
]
那我之前给出的解决方案就直接不行了。但如果仔细观察,您会发现在某些数组中,您的字段名称位于 Y 索引的位置 0、2。这意味着您的字段名称位于成对位置,而字段值位于奇数位置。所以你实际上可以通过 y 循环并检查 Y 索引是否可以被 2 整除。
if(y % 2 == 0 ..){}
并且只有在伴随奇数值时才这样做
if(y % 2 == 0 && employeeData[i][x][y+1]){..}
完整代码如下。
var employeeData = [
[
['firstName', 'Bob', 'weight', '80kg'],
['lastName', 'Lob'],
['age', 22],
['role', 'salesperson']
],
[
['firstName', 'Mary', 'eye color', 'green'],
['lastName', 'Joe'],
['age', 32],
['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
for (var y = 0; y < employeeData[i][x].length; y++) {
if(y % 2 == 0 && employeeData[i][x][y+1]){
newObject[employeeData[i][x][y]] = employeeData[i][x][y+1];
}
}
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
使用 map 和 reduce
更容易完成
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
var d = employeeData.map(
x=>x.reduce((a,b)=>{a[b[0]]=b[1];return a;},{})
)
console.log(d)
这很容易在一行中完成。 Javascript 有专门的功能。
const employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
const res = employeeData.map(data => Object.fromEntries(data))
console.log(res)
干杯
我想使用从嵌套数组中收集的信息将一组嵌套数组转换为对象数组:
之前:
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
之后:
[
{firstName: 'Bob', lastName: 'Lob', age: 22, role: 'salesperson'},
{firstName: 'Mary', lastName: 'Joe', age: 32, role: 'director'}
]
这是我为解决这个问题而编写的函数,但我不太明白循环哪里出了问题:
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
for (var y = 0; y < employeeData[i][y].length; y++) {
newObject[employeeData[i][y][0]] = employeeData[i][y][1];
}
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
提前致谢。
如何修复代码
你只需要 2 个 for 循环: 1.迭代数组 2. 迭代子数组并构造对象
var employeeData = [[["firstName","Bob"],["lastName","Lob"],["age",22],["role","salesperson"]],[["firstName","Mary"],["lastName","Joe"],["age",32],["role","director"]]]
function transformData(employeeData) {
let newObject;
const newArr = [];
for (var i = 0; i < employeeData.length; i++) {
newObject = {}; // init new object
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1]; // iterate inner arrays and assign properties to object
}
newArr.push(newObject);
}
return newArr;
}
console.log(transformData(employeeData));
另一种选择是使用 Array#map to iterate the outer array and Array#reduce 的组合从内部数组构造一个对象:
const employeeData = [[["firstName","Bob"],["lastName","Lob"],["age",22],["role","salesperson"]],[["firstName","Mary"],["lastName","Joe"],["age",32],["role","director"]]]
const result = employeeData.map((arr) =>
arr.reduce((o, [key, value]) => (o[key] = value, o), {})
);
console.log(result);
你的代码有什么问题:
第三级for
循环搞砸了。它应该被删除:
for (var y = 0; y < employeeData[i][x].length; y++) {
// ^ by the way this should be x not y (not fixing the problem though)
因为第三级数组包含 2 个您需要同时使用的元素(作为键值),应该删除它们的 for
循环.
修复:
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1];
}
newArr.push(newObject);
newObject = {};
}
固定代码示例:
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1];
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
备选方案:
您可以将 map
employeeData
数组转换成一个新数组,reduce
将每个子数组转换成一个对象,如下所示:
var result = employeeData.map(function(sub) {
return sub.reduce(function(obj, pair) {
obj[ pair[0] ] = pair[1];
return obj;
}, {});
});
可以使用 ES6 的箭头函数将其缩短为:
let result = employeeData.map(sub => sub.reduce((obj, pair) => (obj[pair[0]] = pair[1], obj), {}));
示例:
let employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
];
let result = employeeData.map(sub => sub.reduce((obj, pair) => (obj[pair[0]] = pair[1], obj), {}));
console.log(result);
您可能只想对外部数组中的每组值使用 Map
而不是 Object
。
那么就是new Map(data);
的一个很简单的转换了。地图已添加到此类数据集的规范中。
var employeeData = [
[['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']],
[['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']]
];
const res = employeeData.map(a => new Map(a));
for (const m of res) {
console.log(m.get("firstName"));
}
但是如果你最终想要数组中的 Object
类型,那么你可以转换每个 Map()
.
var employeeData = [
[['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']],
[['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']]
];
const res = employeeData.map(a => new Map(a));
for (const m of res) {
console.log(m.get("firstName"));
}
const oRes = res.map(m => Object.assign({}, ...Array.from(m.entries()).map(([k,v]) => ({[k]:v}))));
console.log(oRes);
问题出在您对变量 x 和 y 的使用
一方面,这条线
for (var y = 0; y < employeeData[i][y].length; y++)
也许您的意思是改用 employeeData[i][x].length
,因为在您这里,它的行为会很奇怪。
但是,如果将变量 y
替换为 x
(在您的实现中甚至从未使用过)
这是我对您的函数的修改建议:
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1];
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
运行 你的示例进行了这些更改后我得到了正确的输出:
[
{
firstName: 'Bob',
lastName: 'Lob',
age: 22,
role: 'salesperson'
},
{
firstName: 'Mary',
lastName: 'Joe',
age: 32,
role: 'director'
}
]
其他人已经指出 map
数组函数的使用如何可以简化您的任务,这些都是很好的解决方案(比计算循环要好得多),但它们没有解决您实际提出的问题。
您的代码实际上工作得很好,只是您没有提取所有可用的数据。你只有名字和姓氏。通过再添加两行,您可以获得其余数据。此外,甚至不需要第二个循环(它不会伤害您,但实际上并没有帮助,因为您从不在任何地方使用 x
计数器)。
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var y = 0; y < employeeData[i][y].length; y++) {
newObject[employeeData[i][y][0]] = employeeData[i][y][1];
// Now you have to get the next two array elements as well:
newObject[employeeData[i][y+1][0]] = employeeData[i][y+1][1];
newObject[employeeData[i][y+2][0]] = employeeData[i][y+2][1];
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
如果您正确使用索引,可以像您尝试的那样使用 for 循环解决您面临的问题。 如果你像我一样格式化你的数据,你会看到你的索引有三个级别你的 [i,x,y];
例如,对于 employeeData[0],您应该得到:
[
['firstName', 'Bob'],
['lastName', 'Lob'],
['age', 22],
['role', 'salesperson']
]
然后对于 employeeData[0][0] 你应该得到:
['firstName', 'Bob']
对于 employeeData[0][0][0] 你应该得到:'firstName'
要访问 'Bob',您需要访问 employeeData[0][0][1],因为您知道这个内部数组中只有两个元素,所以您不需要遍历它。 正如@TallChuck 所建议的,你的问题很大一部分源于忘记使用你的 x 索引。
var employeeData = [
[
['firstName', 'Bob'],
['lastName', 'Lob'],
['age', 22],
['role', 'salesperson']
],
[
['firstName', 'Mary'],
['lastName', 'Joe'],
['age', 32],
['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1];
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
编辑
如果你注意你的索引,你也可以做一些更复杂的解决方案。假设您有以下数据:
var employeeData = [
[
['firstName', 'Bob', 'weight', '80kg'],
['lastName', 'Lob'],
['age', 22],
['role', 'salesperson']
],
[
['firstName', 'Mary', 'eye color', 'green'],
['lastName', 'Joe'],
['age', 32],
['role', 'director']
]
]
那我之前给出的解决方案就直接不行了。但如果仔细观察,您会发现在某些数组中,您的字段名称位于 Y 索引的位置 0、2。这意味着您的字段名称位于成对位置,而字段值位于奇数位置。所以你实际上可以通过 y 循环并检查 Y 索引是否可以被 2 整除。
if(y % 2 == 0 ..){}
并且只有在伴随奇数值时才这样做
if(y % 2 == 0 && employeeData[i][x][y+1]){..}
完整代码如下。
var employeeData = [
[
['firstName', 'Bob', 'weight', '80kg'],
['lastName', 'Lob'],
['age', 22],
['role', 'salesperson']
],
[
['firstName', 'Mary', 'eye color', 'green'],
['lastName', 'Joe'],
['age', 32],
['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
for (var y = 0; y < employeeData[i][x].length; y++) {
if(y % 2 == 0 && employeeData[i][x][y+1]){
newObject[employeeData[i][x][y]] = employeeData[i][x][y+1];
}
}
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
使用 map 和 reduce
更容易完成var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
var d = employeeData.map(
x=>x.reduce((a,b)=>{a[b[0]]=b[1];return a;},{})
)
console.log(d)
这很容易在一行中完成。 Javascript 有专门的功能。
const employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
const res = employeeData.map(data => Object.fromEntries(data))
console.log(res)
干杯