转换js对象
Transform js object
我正在尝试转换这个对象:
[
{
"keyword":"apple",
"category_1":"object",
"category_2":"living",
"category_3":"fruit",
"count":5
},
{
"keyword":"orange",
"category_1":"object",
"category_2":"living",
"category_3":"fruit",
"count":1
},
{
"keyword":"table",
"category_1":"object",
"category_2":"non living",
"category_3":"house item",
"count":3
},
{
"keyword":"cat",
"category_1":"object",
"category_2":"living",
"category_3":"animal",
"count":4
},
{
"keyword":"stadium",
"category_1":"place",
"category_2":"sport related",
"category_3":"indoor",
"count":2
}
]
变成这样的对象:
[
{
label: 'object',
count: 9,
childs: [
{
label: 'living',
count: 6,
childs: [
{
label: 'fruit',
count: 6,
childs: [
{
keyword: 'apple',
count: 5,
},
{
keyword: 'orange',
count: 1,
}
]
}
]
},
{
label: 'non living',
count: 3,
childs: [
{
label: 'animal',
count: 3,
childs: [
{
keyword: 'cat',
count: 3,
}
]
}
]
}
]
},
{
label: 'place',
count: 2,
childs: [
{
label: 'sport related',
count: 2,
childs: [
{
label: 'indoor',
count: 2,
childs: [
{
keyword: 'stadium',
count: 2,
}
]
}
]
}
]
}
]
我尝试以递归方式使用 Array.reduce,但我在递归方面遇到了麻烦,我总是碰壁。
如您所见,重点是将数组变成一个嵌套对象,将其元素按类别分组(计数部分不是必需的)
如果有人对此有任何后见之明
您可以先将数据转换为嵌套地图,每个地图都以相关类别为键。这允许快速识别将下一个对象注入的正确分支。
然后对其应用递归函数,将基于 Map 的树转换为目标结构,同时增加计数。
代码:
function makeTree(data) {
// Create tree using nested Maps, keyed by category
let main = new Map;
for (let {keyword, category_1, category_2, category_3, count} of data) {
let obj = { keyword, count };
let map = main;
for (let cat of [category_1, category_2, category_3]) {
let child = map.get(cat);
if (!child) map.set(cat, child = new Map);
map = child;
}
let child = map.get(keyword);
if (!child) map.set(keyword, child = { keyword, count: 0 });
child.count += count;
}
// Recursive function to turn the nested Maps into the target structure
function transform(data) {
let parentCount = 0;
let arr = Array.from(data, ([label, value]) => {
let count, children;
if (value instanceof Map) {
([children, count] = transform(value));
value = { label, count, children };
} else {
({ count } = value);
}
parentCount += count;
return value;
});
return [arr, parentCount];
}
return transform(main)[0];
}
// Example run:
let data = [{"keyword":"apple","category_1":"object","category_2":"living","category_3":"fruit","count":5},{"keyword":"orange","category_1":"object","category_2":"living","category_3":"fruit","count":1},{"keyword":"table","category_1":"object","category_2":"non living","category_3":"house item","count":3},{"keyword":"cat","category_1":"object","category_2":"living","category_3":"animal","count":4},{"keyword":"stadium","category_1":"place","category_2":"sport related","category_3":"indoor","count":2}];
console.log(makeTree(data));
我正在尝试转换这个对象:
[
{
"keyword":"apple",
"category_1":"object",
"category_2":"living",
"category_3":"fruit",
"count":5
},
{
"keyword":"orange",
"category_1":"object",
"category_2":"living",
"category_3":"fruit",
"count":1
},
{
"keyword":"table",
"category_1":"object",
"category_2":"non living",
"category_3":"house item",
"count":3
},
{
"keyword":"cat",
"category_1":"object",
"category_2":"living",
"category_3":"animal",
"count":4
},
{
"keyword":"stadium",
"category_1":"place",
"category_2":"sport related",
"category_3":"indoor",
"count":2
}
]
变成这样的对象:
[
{
label: 'object',
count: 9,
childs: [
{
label: 'living',
count: 6,
childs: [
{
label: 'fruit',
count: 6,
childs: [
{
keyword: 'apple',
count: 5,
},
{
keyword: 'orange',
count: 1,
}
]
}
]
},
{
label: 'non living',
count: 3,
childs: [
{
label: 'animal',
count: 3,
childs: [
{
keyword: 'cat',
count: 3,
}
]
}
]
}
]
},
{
label: 'place',
count: 2,
childs: [
{
label: 'sport related',
count: 2,
childs: [
{
label: 'indoor',
count: 2,
childs: [
{
keyword: 'stadium',
count: 2,
}
]
}
]
}
]
}
]
我尝试以递归方式使用 Array.reduce,但我在递归方面遇到了麻烦,我总是碰壁。 如您所见,重点是将数组变成一个嵌套对象,将其元素按类别分组(计数部分不是必需的)
如果有人对此有任何后见之明
您可以先将数据转换为嵌套地图,每个地图都以相关类别为键。这允许快速识别将下一个对象注入的正确分支。
然后对其应用递归函数,将基于 Map 的树转换为目标结构,同时增加计数。
代码:
function makeTree(data) {
// Create tree using nested Maps, keyed by category
let main = new Map;
for (let {keyword, category_1, category_2, category_3, count} of data) {
let obj = { keyword, count };
let map = main;
for (let cat of [category_1, category_2, category_3]) {
let child = map.get(cat);
if (!child) map.set(cat, child = new Map);
map = child;
}
let child = map.get(keyword);
if (!child) map.set(keyword, child = { keyword, count: 0 });
child.count += count;
}
// Recursive function to turn the nested Maps into the target structure
function transform(data) {
let parentCount = 0;
let arr = Array.from(data, ([label, value]) => {
let count, children;
if (value instanceof Map) {
([children, count] = transform(value));
value = { label, count, children };
} else {
({ count } = value);
}
parentCount += count;
return value;
});
return [arr, parentCount];
}
return transform(main)[0];
}
// Example run:
let data = [{"keyword":"apple","category_1":"object","category_2":"living","category_3":"fruit","count":5},{"keyword":"orange","category_1":"object","category_2":"living","category_3":"fruit","count":1},{"keyword":"table","category_1":"object","category_2":"non living","category_3":"house item","count":3},{"keyword":"cat","category_1":"object","category_2":"living","category_3":"animal","count":4},{"keyword":"stadium","category_1":"place","category_2":"sport related","category_3":"indoor","count":2}];
console.log(makeTree(data));