Reorder a JSON collection

2019-06-11 03:02发布

问题:

I have a JSON array fetch from my server which looks like :

     [ {name: "Web Design", id: "27", month_n: "1", data: "68.00"},
     {name: "Web Design", id: "27", month_n: "2", data: "56.00"} ,
     {name: "Homework", id: "4", month_n: "2", data: "15.00"} ,
     {name: "Gaming", id: "12", month_n: "2", data: "5.00"} ]

On the client side, I want to reorder this to have something similar to :

 [{name: "Web Design", data:[68.00,56.00]}, {name:"Homework", data:[0,15]} and so on...

Where the "data" value is grouped by the "id" number and the month number (by default 0 if there's no month that match).

What's the best way ? I tried it the pure JavaScript way but I'm getting a hard time ! I have also heard It is easier with underscore JS. But don't know where to start.

Will someone please enlighten me ?

回答1:

One way to do this in vanilla JavaScript, is to use a helper object as in the following code.

In a first step, we identify all distinct name values and group all data field by them. In the second step, the helper object is converted back to an array.

var arr =  [ {name: "Web Design", id: "27", month_n: "1", data: "68.00"},
     {name: "Web Design", id: "27", month_n: "2", data: "56.00"} ,
     {name: "Homework", id: "4", month_n: "2", data: "15.00"} ,
     {name: "Gaming", id: "12", month_n: "2", data: "5.00"} ];

// use a helper object to identify all distinct "names"
var helper = {};
for( var i=arr.length; i--; ) {
  // init an array, if it is not there
  helper[ arr[i]['name'] ] = helper[ arr[i]['name'] ] || [];

  // add the newest element
  helper[ arr[i]['name'] ].push( helper[ arr[i]['data'] ] );
}

// convert back to an array
var newArr = [];
for( var key in helper ) {
 if( helper.hasOwnProperty( key ) ) {
   newArr.push( { 'name': key, 'data': helper[key] } );
 }
}


回答2:

This can be done by two operations:

  1. Groupby [name] field, then
  2. Pluck [data] fields

There are pure JS array prototype extensions libraries to achieve this and many other operations with couple of lines. You may take a look at underscore.js. I have also written a simple JS library jsList. It comes with many unit-tests to use as example.

You only need to write these lines:

var arr = [ {name: "Web Design", id: "27", month_n: "1", data: "68.00"},
            {name: "Web Design", id: "27", month_n: "2", data: "56.00"} ,
            {name: "Homework", id: "4", month_n: "2", data: "15.00"} ,
            {name: "Gaming", id: "12", month_n: "2", data: "5.00"} ];

var temp = arr.groupBy(function(item){ return item.name });

var result = [];
for(var key in temp){
    result.push({name: key, data: temp[key].pluck('data')});
}

You may use Object.keys to avoid the for loop, but it only comes with Javascript 1.8.5 or later.

Thanks.