Is there a built-in Javascript function to transform a list of dictionaries:
const L =
[ { "day": "20201210", "count": "100" }
, { "day": "20201211", "count": "120" }
, { "day": "20201212", "count": "90" }
, { "day": "20201213", "count": "150" }
]
into a dictionary of lists like this:
const D =
{ "day" : [ "20201210", "20201211", "20201212", "20201213"]
, "count" : [ "100", "120", "90", "150"]
}
? If not what's the simplest way to do it in JS?
(It is a little-bit similar to matrix "transpose" operation).
Note: here it's a transpose and not a groupby like in Most efficient method to groupby on an array of objects
Is there a built-in Javascript function to transform a list of dictionaries:
const L =
[ { "day": "20201210", "count": "100" }
, { "day": "20201211", "count": "120" }
, { "day": "20201212", "count": "90" }
, { "day": "20201213", "count": "150" }
]
into a dictionary of lists like this:
const D =
{ "day" : [ "20201210", "20201211", "20201212", "20201213"]
, "count" : [ "100", "120", "90", "150"]
}
? If not what's the simplest way to do it in JS?
(It is a little-bit similar to matrix "transpose" operation).
Note: here it's a transpose and not a groupby like in Most efficient method to groupby on an array of objects
Share Improve this question edited Dec 21, 2020 at 12:04 Basj asked Dec 21, 2020 at 11:43 BasjBasj 46.4k110 gold badges452 silver badges804 bronze badges 6- Does this answer your question? Group by multiple values Underscore.JS but keep the keys and values – arizafar Commented Dec 21, 2020 at 11:50
- using simple js Most efficient method to groupby on an array of objects – arizafar Commented Dec 21, 2020 at 11:52
- 1 This question should be reopened. This is not even related to grouping of array elements. The second linked question is related but this is still different enough to justify a new question. – lex82 Commented Dec 21, 2020 at 12:07
- I changed my answer to work with an unknown list of keys – Mister Jojo Commented Dec 21, 2020 at 12:36
- I changed my answer to make it a universal function, in the idea of your matrix function – Mister Jojo Commented Dec 21, 2020 at 12:45
6 Answers
Reset to default 2Assuming all objects have the same keys and your array is not empty, this will work:
let D = {};
Object.keys(L[0]).forEach(k => {
D[k] = L.map(o => o[k]);
});
There are certainly more efficient solutions but this is short and concise and not too bad in terms of efficiency.
Here's a fairly short and efficient method for general values.
L.forEach(o => {
Object.keys(o).forEach(k => {
D[k] ||= [];
D[k].push(o[k]);
});
});
const L = [{
"day": "20201210",
"count": "100"
}, {
"day": "20201211",
"count": "120"
}, {
"day": "20201212",
"count": "90"
}, {
"day": "20201213",
"count": "150"
}]
let D = {};
L.forEach(o => {
Object.keys(o).forEach(k => {
D[k] ||= [];
D[k].push(o[k]);
});
});
console.log(D);
I don't think such a function exists, at least in vanilla JavaScript.
A simple, pure vanilla and clear to understand way of doing it would be like this:
var L = [
{
"day": "20201210",
"count": "100"
},
{
"day": "20201211",
"count": "120"
},
{
"day": "20201212",
"count": "90"
},
{
"day": "20201213",
"count": "150"
}
];
var D = { };
for (var dict in L)
{
for (var key in L[dict])
{
if (D[key] == null) {
D[key] = [ ];
}
D[key].push(L[dict][key]);
}
}
This is definitely not the most concise or most optimized way of doing it, though it will work.
You can just restructure your array of dictionaries as such, and re-map it with Array.prototype.map
E.g. (The following practice requires to iterate the elements with map
N * X
times where N
is the length of L
and X
is the amount of properties you'd want to have in D
, ignore this if you have many properties you'd want to watch.)
But, this is the easiest readable approach that I'd want to introduce to you before the 2nd approach.
const L = [{"day":"20201210","count":"100"},{"day":"20201211","count":"120"},{"day":"20201212","count":"90"},{"day":"20201213","count":"150"}];
const D = {
'day': L.map(elem => elem['day']),
'count': L.map(elem => elem['count']),
};
console.log(D);
Another approach I'd suggest is to use Array.prototype.reduce, this is by far favored in your case as it's easily expandable by adding more properties to the initial array.
const L = [{"day":"20201210","count":"100"},{"day":"20201211","count":"120"},{"day":"20201212","count":"90"},{"day":"20201213","count":"150"}];
const D = L.reduce((acc, cv) => {
for (const propertyToGrab in acc) {
if (cv.hasOwnProperty(propertyToGrab)) {
acc[propertyToGrab].push(cv[propertyToGrab]);
}
}
return acc;
}, {
'day': [],
'count': []
});
console.log(D);
const D={day:[], count:[]};
for(const item of L){
D.day.push(item.day);
D.count.push(item.count);
}
const input = [{"day":"20201210","count":"100"},{"day":"20201211","count":"120"},{"day":"20201212","count":"90"},{"day":"20201213","count":"150"}];
// Create a variable that will store the result
let result = {};
// Loop through the input with forEach
input.forEach((element) => {
// Loop through the keys
for(let key in element) {
// Check if a key is not exist in the result
if(!result.hasOwnProperty(key)) {
// Then create an key and assign an empty array to it
result[key] = [];
}
// Push the elemnts to the array.
result[key].push(element[key]);
}
});