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 bee [[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);
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 bee [[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);
Share
edited Mar 23, 2018 at 18:45
CRice
32.3k5 gold badges61 silver badges73 bronze badges
asked Mar 23, 2018 at 18:29
ThomasThomas
1811 silver badge10 bronze badges
0
6 Answers
Reset to default 2You 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);
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:
Array.prototype.reduce()
Arrow Functions
Comma Operator
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 bination of javascript built-ins one can e 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 e.g.
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);