简体   繁体   中英

Turn groups into concat of arrays javascript

I have managed to split an array into separate groups based on key value. What I want to achieve is to turn these groups which can be more or less into an array, so my groups become [[Regio__c],[Categorie__c]] instead of {Regio__c:[],Categorie__c:[]} . This with plain javascript no libraries.

I tried: return [key].concat.split; this returns undefined.

Below is my code in a snippet

 var filter = [{ "Id": "120", "arrayPicklist": "Categorie__c" }, { "Id": "121", "arrayPicklist": "Regio__c" }, { "Id": "122", "arrayPicklist": "Categorie__c" }, { "Id": "123", "arrayPicklist": "Regio__c" }, { "Id": "121", "arrayPicklist": "Regio__c" } ] function splitArrayByValue(arr, key) { var split = {}; for (var i = 0; i < arr.length; i++) { var p = arr[i][key]; if (!split[p]) { split[p] = []; } split[p].push(arr[i]) } return split; } var buckets2 = splitArrayByValue(filter, 'arrayPicklist'); console.log(buckets2); 

You can use .reduce() :

 let data = [ {"Id":"120", "arrayPicklist":"Categorie__c"}, {"Id":"121", "arrayPicklist":"Regio__c"}, {"Id":"122", "arrayPicklist":"Categorie__c"}, {"Id":"123", "arrayPicklist":"Regio__c"}, {"Id":"121", "arrayPicklist":"Regio__c"} ]; let keys = [...new Set(data.map(({arrayPicklist}) => arrayPicklist))]; /* * let keys = ["Categorie__c", "Regio__c"]; * In case you wants to use hard code values */ let result = data.reduce((r, c) => ( r[keys.indexOf(c["arrayPicklist"])].push(c), r ), [[], []]); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Useful Resources:

You almost there, you need to get the values. An alternative is using the function Object.values

 var filter = [{ "Id": "120", "arrayPicklist": "Categorie__c" }, { "Id": "121", "arrayPicklist": "Regio__c" }, { "Id": "122", "arrayPicklist": "Categorie__c" }, { "Id": "123", "arrayPicklist": "Regio__c" }, { "Id": "121", "arrayPicklist": "Regio__c" }] function splitArrayByValue(arr, key) { var split = {}; for (var i = 0; i < arr.length; i++) { var p = arr[i][key]; if (!split[p]) { split[p] = []; } split[p].push(arr[i]) } return Object.values(split); } var buckets2 = splitArrayByValue(filter, 'arrayPicklist'); console.log(buckets2); 

You can use the function reduce to group and then the function Object.values to get the desired output.

 var filter = [{"Id":"120","arrayPicklist":"Categorie__c"},{"Id":"121","arrayPicklist":"Regio__c"},{"Id":"122","arrayPicklist":"Categorie__c"},{"Id":"123","arrayPicklist":"Regio__c"},{"Id":"121","arrayPicklist":"Regio__c"}]; var result = Object.values(filter.reduce((a, {Id, arrayPicklist}) => { (a[arrayPicklist] || (a[arrayPicklist] = [])).push({Id, arrayPicklist}); return a; }, {})); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Just return Object.values(split) instead of split in splitArrayByValue function.

 var filter = [{"Id":"120","arrayPicklist": "Categorie__c"},{"Id":"121","arrayPicklist":"Regio__c"}, {"Id":"122","arrayPicklist":"Categorie__c"},{"Id":"123","arrayPicklist":"Regio__c"}, {"Id":"121","arrayPicklist":"Regio__c"}] function splitArrayByValue(arr, key) { var split = {}; for (var i=0; i<arr.length; i++) { var p = arr[i][key]; if (!split[p]) { split[p] = []; } split[p].push(arr[i]) } return Object.values(split);//<---- just return Object.values(split) instead of split } var buckets2 = splitArrayByValue(filter,'arrayPicklist'); console.log(buckets2); 

Make a set of all possible categories ( arrayPicklist ). For each value in this set, filter the array and create a group:

 var array = [ {"Id": "120", "arrayPicklist": "Categorie__c"}, {"Id": "121", "arrayPicklist": "Regio__c"}, {"Id": "122", "arrayPicklist": "Categorie__c"}, {"Id": "123", "arrayPicklist": "Regio__c"}, {"Id": "121", "arrayPicklist": "Regio__c"} ] let groups = [...new Set(array.map(x => x.arrayPicklist))] .map(p => array.filter(x => x.arrayPicklist === p)); console.log(groups) 

That said, you should really consider using a library. Well-designed and well-tested tools are always preferred to any fragile ad-hoc combination of javascript built-ins one can come up with. With lodash , your problem is solved in one line:

let groups = _.values(_.groupBy(array, 'arrayPicklist'))

as it is with Ramda :

let groups  = R.values(R.groupBy(x => x.arrayPicklist, array))

If I understand correctly, you want to get the values of the object as an array instead. You can acheive this using the following methods:

1. Object.values :

When you return from splitArrayByValue , return this:

return Object.values(split);

instead of:

return split;

Object.values works only in ECMAScript 2017. If your have the older ECMA, then use the second method, which acheives the same

2. Object.keys & Array#map :

As above, instead of returning split directly, return this:

return Object.keys(split).map(function(key) {
  return split[key];
});

or shorter using an arrow function:

return Object.keys(split).map(key => split[key]);

Note: In both the above methods, the order of the subarrays is not specified. It could be anything. It could be [[Regio__c], [Categorie__c]] as it could be [[Categorie__c], [Regio__c]] as object in javascript don't preserve the order of their key-value pairs.

I understand that you want to end up with a 2D array with the first level representing the arrayPicklist value. If that is correct, you could use map and Set to achieve what you want eg

var filter = [{"Id":"120","arrayPicklist":
"Categorie__c"},{"Id":"121","arrayPicklist":"Regio__c"},
{"Id":"122","arrayPicklist":"Categorie__c"},{"Id":"123","arrayPicklist":"Regio__c"},
{"Id":"121","arrayPicklist":"Regio__c"}]


function splitArrayByValue(arr, key) {
  let keys = arr.map(entry => {
    return entry[key];
  });

  let unique = [...new Set(keys.concat())]; 

  let split = new Array(unique.length);
  for (var i = 0; i < arr.length; i++) {
    let p = arr[i][key];
    let index = unique.indexOf(p);

    if (!split[index]) split[index] = [];
    split[index].push(arr[i])
  }
  return split;
}


var buckets2 = splitArrayByValue(filter,'Id');

console.log(buckets2);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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