从树对象构建对象数组
build array of object from tree object
我正在尝试进入 javascript 的内置 reduce
函数,并借助于在数组中构建对象。
但是你可以使用任何你想要的功能或方法。
预期输出
[
{ 'team1': [14697807552, 6858384], '2021': [14697807552, 6858384], 'pepsi': [null, null], 'cola': [14697807552, 6858384] },
{ 'team2': [10268029152, 6922128], '2021': [10268029152, 6922128], 'pepsi': [null, 4800], 'cola': [10268029152, 6917328] },
]
我尝试做的事情
我创建了一个函数,它将数组作为参数并为每个数组的元素调用 reduce。
function transform(arr, obj = {}) {
return arr.reduce((acc, item) => {
const newObj = {};
newObj[item.name] = item.metrics;
acc.push(newObj);
if (item.children) {
transform(item.children, newObj);
}
return acc;
}, []);
}
console.log(transform(arr))
<script>
const arr = [{
"name": "team1",
"metrics": [
14697807552,
6858384
],
"children": [{
"name": "2021",
"metrics": [
14697807552,
6858384
],
"children": [{
"name": "pepsi",
"metrics": [
null,
null
]
},
{
"name": "cola",
"metrics": [
14697807552,
6858384
]
}
]
}]
},
{
"name": "team2",
"metrics": [
10268029152,
6922128
],
"children": [{
"name": "2021",
"metrics": [
10268029152,
6922128
],
"children": [{
"name": "pepsi",
"metrics": [
null,
4800
]
},
{
"name": "cola",
"metrics": [
10268029152,
6917328
]
}
]
}]
}
]
</script>
但它给了我不想要的输出:
[
{ team1: [ 14697807552, 6858384 ] },
{ team2: [ 10268029152, 6922128 ] }
]
如果您不明白我的问题或有疑问,请问我。感谢关注!
transform
函数不对第二个参数 obj
执行任何操作,因此当您递归调用 transform
时,newObj
不会被扩展:这使得递归调用失去了任何预期的效果。
您可以使用 Object.assign
来 收集 所有从递归返回的对象,然后将它们合并为一个对象,而不是传递第二个参数:
const convert = arr =>
arr?.map(({name, metrics, children}) =>
Object.assign({[name]: metrics}, ...convert(children))) ?? [];
const arr = [{"name": "team1","metrics": [14697807552,6858384],"children": [{"name": "2021","metrics": [14697807552,6858384],"children": [{"name": "pepsi","metrics": [null,null]},{"name": "cola","metrics": [14697807552,6858384]}]}]},{"name": "team2","metrics": [10268029152,6922128],"children": [{"name": "2021","metrics": [10268029152,6922128],"children": [{"name": "pepsi","metrics": [null,4800]},{"name": "cola","metrics": [10268029152,6917328]}]}]}];
console.log(convert(arr));
请注意,像“2021”这样的 属性 是一个 index 并且将排在其他 non-index 属性之前。即使你打印一个像 { 'a': 2, '2021': 1 }
这样的对象,你也会因为同样的原因得到相反顺序的键。
如果对象键的 order 对您很重要,那么您应该使用成对数组而不是普通对象。当你需要顺序时,数组是选择的结构,当顺序不是必需的时候应该使用普通对象。
我找到了一些不同的解决方案:)
它比@trincot 的回答长,但也有效
const arr = [{"name": "team1","metrics": [14697807552,6858384],"children": [{"name": "2021","metrics": [14697807552,6858384],"children": [{"name": "pepsi","metrics": [null,null]},{"name": "cola","metrics": [14697807552,6858384]}]}]},{"name": "team2","metrics": [10268029152,6922128],"children": [{"name": "2021","metrics": [10268029152,6922128],"children": [{"name": "pepsi","metrics": [null,4800]},{"name": "cola","metrics": [10268029152,6917328]}]}]}];
const handleArr = (list, rez) => {
list.forEach((item) => {
rez[item.name] = item.metrics;
item.children && handleArr(item.children, rez);
});
};
const handle = (list) => {
const rezArr = [];
for (const item of list) {
const rezObj = { [item.name]: item.metrics };
item.children && handleArr(item.children, rezObj);
rezArr.push(rezObj);
}
return rezArr;
};
console.log(handle(arr));
这种方法 returns 不同的结果,并使用所有先前的信息来获得数据的 denormalization。
const
flat = array => array.flatMap(({ name, metrics, children }) => children
? flat(children).map(q => ({ [name]: metrics, ...q }))
: { [name]: metrics }),
data = [{ name: "team1", metrics: [14697807552, 6858384], children: [{ name: "2021", metrics: [14697807552, 6858384], children: [{ name: "pepsi", metrics: [null, null] }, { name: "cola", metrics: [14697807552, 6858384] }] }] }, { name: "team2", metrics: [10268029152, 6922128], children: [{ name: "2021", metrics: [10268029152, 6922128], children: [{ name: "pepsi", metrics: [null, 4800] }, { name: "cola", metrics: [10268029152, 6917328] }] }] }],
result = flat(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我正在尝试进入 javascript 的内置 reduce
函数,并借助于在数组中构建对象。
但是你可以使用任何你想要的功能或方法。
预期输出
[
{ 'team1': [14697807552, 6858384], '2021': [14697807552, 6858384], 'pepsi': [null, null], 'cola': [14697807552, 6858384] },
{ 'team2': [10268029152, 6922128], '2021': [10268029152, 6922128], 'pepsi': [null, 4800], 'cola': [10268029152, 6917328] },
]
我尝试做的事情
我创建了一个函数,它将数组作为参数并为每个数组的元素调用 reduce。
function transform(arr, obj = {}) {
return arr.reduce((acc, item) => {
const newObj = {};
newObj[item.name] = item.metrics;
acc.push(newObj);
if (item.children) {
transform(item.children, newObj);
}
return acc;
}, []);
}
console.log(transform(arr))
<script>
const arr = [{
"name": "team1",
"metrics": [
14697807552,
6858384
],
"children": [{
"name": "2021",
"metrics": [
14697807552,
6858384
],
"children": [{
"name": "pepsi",
"metrics": [
null,
null
]
},
{
"name": "cola",
"metrics": [
14697807552,
6858384
]
}
]
}]
},
{
"name": "team2",
"metrics": [
10268029152,
6922128
],
"children": [{
"name": "2021",
"metrics": [
10268029152,
6922128
],
"children": [{
"name": "pepsi",
"metrics": [
null,
4800
]
},
{
"name": "cola",
"metrics": [
10268029152,
6917328
]
}
]
}]
}
]
</script>
但它给了我不想要的输出:
[
{ team1: [ 14697807552, 6858384 ] },
{ team2: [ 10268029152, 6922128 ] }
]
如果您不明白我的问题或有疑问,请问我。感谢关注!
transform
函数不对第二个参数 obj
执行任何操作,因此当您递归调用 transform
时,newObj
不会被扩展:这使得递归调用失去了任何预期的效果。
您可以使用 Object.assign
来 收集 所有从递归返回的对象,然后将它们合并为一个对象,而不是传递第二个参数:
const convert = arr =>
arr?.map(({name, metrics, children}) =>
Object.assign({[name]: metrics}, ...convert(children))) ?? [];
const arr = [{"name": "team1","metrics": [14697807552,6858384],"children": [{"name": "2021","metrics": [14697807552,6858384],"children": [{"name": "pepsi","metrics": [null,null]},{"name": "cola","metrics": [14697807552,6858384]}]}]},{"name": "team2","metrics": [10268029152,6922128],"children": [{"name": "2021","metrics": [10268029152,6922128],"children": [{"name": "pepsi","metrics": [null,4800]},{"name": "cola","metrics": [10268029152,6917328]}]}]}];
console.log(convert(arr));
请注意,像“2021”这样的 属性 是一个 index 并且将排在其他 non-index 属性之前。即使你打印一个像 { 'a': 2, '2021': 1 }
这样的对象,你也会因为同样的原因得到相反顺序的键。
如果对象键的 order 对您很重要,那么您应该使用成对数组而不是普通对象。当你需要顺序时,数组是选择的结构,当顺序不是必需的时候应该使用普通对象。
我找到了一些不同的解决方案:) 它比@trincot 的回答长,但也有效
const arr = [{"name": "team1","metrics": [14697807552,6858384],"children": [{"name": "2021","metrics": [14697807552,6858384],"children": [{"name": "pepsi","metrics": [null,null]},{"name": "cola","metrics": [14697807552,6858384]}]}]},{"name": "team2","metrics": [10268029152,6922128],"children": [{"name": "2021","metrics": [10268029152,6922128],"children": [{"name": "pepsi","metrics": [null,4800]},{"name": "cola","metrics": [10268029152,6917328]}]}]}];
const handleArr = (list, rez) => {
list.forEach((item) => {
rez[item.name] = item.metrics;
item.children && handleArr(item.children, rez);
});
};
const handle = (list) => {
const rezArr = [];
for (const item of list) {
const rezObj = { [item.name]: item.metrics };
item.children && handleArr(item.children, rezObj);
rezArr.push(rezObj);
}
return rezArr;
};
console.log(handle(arr));
这种方法 returns 不同的结果,并使用所有先前的信息来获得数据的 denormalization。
const
flat = array => array.flatMap(({ name, metrics, children }) => children
? flat(children).map(q => ({ [name]: metrics, ...q }))
: { [name]: metrics }),
data = [{ name: "team1", metrics: [14697807552, 6858384], children: [{ name: "2021", metrics: [14697807552, 6858384], children: [{ name: "pepsi", metrics: [null, null] }, { name: "cola", metrics: [14697807552, 6858384] }] }] }, { name: "team2", metrics: [10268029152, 6922128], children: [{ name: "2021", metrics: [10268029152, 6922128], children: [{ name: "pepsi", metrics: [null, 4800] }, { name: "cola", metrics: [10268029152, 6917328] }] }] }],
result = flat(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }