我有这样的JSON对象:
[{
"name" : "cat",
"value" : 17,
"group" : "animal",
},
{
"name" : "dog",
"value" : 6,
"group" : "animal",
},
{
"name" : "snak",
"value" : 2,
"group" : "animal",
},
{
"name" : "tesla",
"value" : 11,
"group" : "car",
},
{
"name" : "bmw",
"value" : 23,
"group" : "car",
}]
我想通过JS将JSON转换为以下格式:
[{
"name":"animal",
"children":[
{"name":"cat", "value":17},
{"name":"dog", "value":6},
{"name":"snak", "value":2}
]},
{
"name":"car",
"children":[
{"name":"bmw", "value":11},
{"name":"tesla", "value":23}
]}]
我尝试通过Reduce
函数进行转换和过滤,但是我无法转换为这种格式。
编辑:
我测试的代码是这样。
let groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
let groubedByExchange=groupBy(JSON_data, 'group');
答案 0 :(得分:3)
您可以构建一个数组并在该数组中搜索相同的组。
var array = [{ name: "cat", value: 17, group: "animal" }, { name: "dog", value: 6, group: "animal" }, { name: "snak", value: 2, group: "animal" }, { name: "tesla", value: 11, group: "car" }, { name: "bmw", value: 23, group: "car" }],
result = array.reduce((r, { group: name, ...object }) => {
var temp = r.find(o => o.name === name);
if (!temp) r.push(temp = { name, children: [] });
temp.children.push(object);
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 1 :(得分:3)
一个简单的解决方案是构建中间词典,然后将其转换为输出结构。
您可以使用Array.reduce()
,Object.entries()
和Array.map()
来做到这一点:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const result = Object.entries(data.reduce((acc, { name, value, group }) => {
acc[group] = (acc[group] || []);
acc[group].push({ name, value });
return acc;
}, {})).map(([key, value]) => ({ name: key, children: value }));
console.log(result);
使用扩频运算符可使它缩短一行并仍然可读:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const result = Object.entries(data.reduce((acc, { name, value, group }) => {
acc[group] = [...(acc[group] || []), { name, value }];
return acc;
}, {})).map(([key, value]) => ({ name: key, children: value }));
console.log(result);
和一个逗号分隔符一起缩短了一个衬里:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const result = Object.entries(data.reduce((acc, { name, value, group }) =>
(acc[group] = [...(acc[group] || []), { name, value }], acc)
, {})).map(([key, value]) => ({ name: key, children: value }));
console.log(result);
Object.assign()
可以完成同样的操作:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const result = Object.entries(data.reduce((acc, { name, value, group }) =>
Object.assign(acc, { [group]: [...(acc[group] || []), { name, value }] })
, {})).map(([key, value]) => ({ name: key, children: value }));
console.log(result);
最后,虽然更长,但具有可重复使用的groupBy
函数:
const data = [
{ "name" : "cat", "value" : 17, "group" : "animal" },
{ "name" : "dog", "value" : 6, "group" : "animal" },
{ "name" : "snak", "value" : 2, "group" : "animal" },
{ "name" : "tesla", "value" : 11, "group" : "car" },
{ "name" : "bmw", "value" : 23, "group" : "car" }
];
const groupBy = prop => data => {
return data.reduce((dict, item) => {
const { [prop]: _, ...rest } = item;
dict[item[prop]] = [...(dict[item[prop]] || []), rest];
return dict;
}, {});
};
const result = Object.entries(groupBy('group')(data))
.map(([key, value]) => ({ name: key, children: value }));
console.log(result);
答案 2 :(得分:2)
使用Array#from,Array#reduce,Array#concat,解构,扩展语法和Map。
const data=[{"name":"cat","value":17,"group":"animal",},{"name":"dog","value":6,"group":"animal",},{"name":"snak","value":2,"group":"animal",},{"name":"tesla","value":11,"group":"car",},{"name":"bmw","value":23,"group":"car",}];
const res = Array.from(
data.reduce((a,{group, ...rest})=>{
return a.set(group, [rest].concat(a.get(group)||[]));
}, new Map())
).map(([group, children])=>({group,children}));
console.log(res);
答案 3 :(得分:1)
const arr = [{
"name": "cat",
"value": 17,
"group": "animal",
},
{
"name": "dog",
"value": 6,
"group": "animal",
},
{
"name": "snak",
"value": 2,
"group": "animal",
},
{
"name": "tesla",
"value": 11,
"group": "car",
},
{
"name": "bmw",
"value": 23,
"group": "car",
}
]
const newFormat = arr.reduce((pre, cur) => {
const group = pre.find(grp => grp.name === cur.group)
if (group) {
group.children.push({
name: cur.name,
value: cur.value
})
return pre
}
const newGroup = {
name: cur.group,
children: [{
name: cur.name,
value: cur.value
}]
}
pre.push(newGroup)
return pre
}, [])
console.log(newFormat)
你去了。 首先,您尝试在新数组中找到该组,如果存在该组,则将其添加到该组中。如果没有,则创建group and children数组并将其推入数组
答案 4 :(得分:1)
//COMPONENT HTML FILE
<mat-sidenav-container class="sidenav-container">
<mat-sidenav
#drawer
[ngClass]="{ hidden: !(isHandset$ | async) }"
class="sidenav"
fixedInViewport="false"
[attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
[mode]="(isHandset$ | async) ? 'over' : 'side'"
[opened]="!(isHandset$ | async)"
>
<mat-toolbar>Navigation</mat-toolbar>
<mat-nav-list>
<a
*ngFor="let navItem of navItems"
routerLinkActive="active"
mat-list-item
routerLink="{{ navItem.path }}"
>{{ navItem.text }}</a
>
<div *ngIf="!isAuthorized; else loggedIn">
<a mat-list-item (click)="loginDialog()">Login</a>
<a mat-list-item (click)="joinDialog()">Join</a>
</div>
<ng-template #loggedIn>
<a mat-list-item href="#">Geebrox</a>
</ng-template>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar class="nav-header">
<mat-toolbar-row [ngClass]="{ 'nav-expand': navExpand }">
<img
routerLink="/"
class="logo-default"
src="./assets/img/header/nav/nav-logo-default.jpg"
alt="Honadon"
/>
<mat-chip-list *ngIf="!(isHandset$ | async)">
<a
*ngFor="let navItem of navItems"
routerLinkActive="active"
mat-button
routerLink="{{ navItem.path }}"
>{{ navItem.text }}</a
>
</mat-chip-list>
<span class="spacer"></span>
<mat-chip-list *ngIf="!isAuthorized && !(isHandset$ | async)">
<mat-chip class="nav-button" (click)="loginDialog()">Login</mat-chip>
<span class="divider">or</span>
<mat-chip class="nav-button" (click)="joinDialog()">Join</mat-chip>
</mat-chip-list>
<mat-chip-list *ngIf="isAuthorized && !(isHandset$ | async)">
<mat-chip><a href="#">sample_user</a></mat-chip>
</mat-chip-list>
<button
type="button"
aria-label="Toggle sidenav"
mat-icon-button
(click)="drawer.toggle()"
*ngIf="(isHandset$ | async)"
>
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
</mat-toolbar-row>
</mat-toolbar>
<ng-content></ng-content>
</mat-sidenav-content>
</mat-sidenav-container>
答案 5 :(得分:0)
这将是我的ES6解决方案,使用map和reduce:
const data = [
{
name: "cat",
value: 17,
group: "animal"
},
{
name: "dog",
value: 6,
group: "animal"
},
{
name: "snak",
value: 2,
group: "animal"
},
{
name: "tesla",
value: 11,
group: "car"
},
{
name: "bmw",
value: 23,
group: "car"
}
];
const grouped = data.reduce((acc, currItem) => {
const groupKey = currItem.group;
if (!acc[groupKey]) {
acc[groupKey] = [currItem];
} else {
acc[groupKey].push(currItem);
}
return acc;
}, {});
const res = Object.keys(grouped).map(key => ({
name: key,
children: grouped[key].map(groupItem => ({
name: groupItem.name,
value: groupItem.value
}))
}));
console.log(res);
检查控制台输出以查看中间结果。
我认为其他一些答案使用了不必要的find()(即O(n)),而您只需测试O(1)中是否已有当前的组密钥即可。
为清楚起见,我将分组结果存储在中间变量grouped
中,但可以将其全部内联。
答案 6 :(得分:0)
您在这里。您可以使用lodash来实现相同的目的。
var data = [{
"name": "cat",
"value": 17,
"group": "animal",
},
{
"name": "dog",
"value": 6,
"group": "animal",
},
{
"name": "snak",
"value": 2,
"group": "animal",
},
{
"name": "tesla",
"value": 11,
"group": "car",
},
{
"name": "bmw",
"value": 23,
"group": "car",
}
]
var result = _(data)
.groupBy('group')
.map((group, name) =>
({
name,
children: _.map(group, ({
name: name,
value
}) => ({
name,
value
}))
}))
.value()
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>