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.