简体   繁体   English

转换JSON格式(分组依据)

[英]Convert JSON format (Group by)

I have JSON object like this: 我有这样的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",
}]

I want to convert this JSON to below format by JS: 我想通过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}
]}]

I try to convert and filter by Reduce function but I couldn't convert to this format. 我尝试通过Reduce函数进行转换和过滤,但我无法转换为此格式。

EDIT: 编辑:

The code I tested was this. 我测试的代码就是这个。

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');

You could build an array and search for the same group in the array. 您可以构建一个数组并在数组中搜索相同的组。

 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; } 

A simple solution is to build an intermediate dictonary and then transform it to your output structure. 一个简单的解决方案是构建一个中间的dictonary,然后将其转换为您的输出结构。

You can use Array.reduce() , Object.entries() and Array.map() to do it: 您可以使用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); 

Using the spread operator makes it one line shorter and still readable: 使用扩展运算符使其缩短一行并仍然可读:

 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); 

And one liner shorter with the comma operator: 使用逗号运算符缩短一个衬垫:

 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); 

The same can be done with Object.assign() : 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); 

And finally, a bit longer but with a reusable groupBy function: 最后,有点长,但有一个可重用的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); 

Using Array#from, Array#reduce, Array#concat, destructuring, spread syntax and Map. 使用Array#from,Array#reduce,Array#concat,destructuring,spread syntax和Map。

  1. reorganize your data structure by using Map 使用Map重新组织您的数据结构
  2. restructuring your data using .map 使用.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); 

 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) 

there you go. 你去吧 first you try to find that group in new array, if it exists you add that child to it. 首先,您尝试在新数组中找到该组,如果存在,则将该子组添加到该组中。 if not, you create the group and children array and push it to the array 如果没有,则创建group和children数组并将其推送到数组

const transform = things =>
  things.reduce((acc, { name, value, group }) => {
    const existingGroup = acc.find(g => g.name === group) || {};
    return [
      ...acc.filter(g => g.name !== group),
      {
        ...existingGroup,
        name: group,
        children: [...(existingGroup.children || []), { name, value }],
      },
    ];
  }, []);

This would be my ES6 solution, using map and reduce: 这将是我的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); 

Check the console output to see the intermediate results. 检查控制台输出以查看中间结果。

I think some of the other answers use an unnecessary find() (which is O(n)) while you can just test if a current group key is already in there in O(1). 我认为其他一些答案使用了一个不必要的find()(即O(n)),而你可以只测试当前的组密钥是否已经存在于O(1)中。

I'm storing the grouped results in a intermediate variable grouped for clarity, but it can all be inlined. 我存储在一个中间变量分组结果grouped为清楚起见,但都可以被内联。

Here you go. 干得好。 You can use lodash to achieve the same. 您可以使用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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM