Reputation: 1281
I have an array of objects, and I'm struggling to come up with a better way to map it to two new arrays: one containing a list of unique code values, and the other containing a count of occurrences of each code.
Note: The order of the resulting arrays are important. For instance, data[1] should be the number of occurrences of labels[1].
This is what I have so far, but I can't seem to find a way to do it without multiple loops...
var objs = [{
code: 200,
message: 'a'
},
{
code: 300,
message: 'b'
},
{
code: 200,
message: 'c'
},
{
code: 400,
message: 'd'
},
{
code: 200,
message: 'e'
},
];
var data = [];
var labels = [];
var bins = objs
.reduce((codes, obj) => {
let key = obj.code;
codes[key] ? codes[key]++ : codes[key] = 1;
return codes;
}, {});
for (var prop in bins) {
if (!bins.hasOwnProperty(prop))
continue;
labels.push(prop);
data.push(bins[prop]);
}
console.log('data', data); // [3, 1, 1]
console.log('labels', labels); // ['200', '300', '400']
Upvotes: 1
Views: 237
Reputation: 193248
You can use reduce the array of objects into a Map, and then extract the values and the keys into arrays:
const values = [{ code: 200, message: 'a' }, { code: 300, message: 'b' }, { code: 200, message: 'c' }, { code: 400, message: 'd' }, { code: 200, message: 'e' }];
const counts = values.reduce((m, { code }) => m.set(code, (m.get(code) || 0) + 1), new Map());
const data = [...counts.values()];
const label = [...counts.keys()];
console.log(data);
console.log(label);
Upvotes: 1
Reputation: 386868
You could take a hash table for the indices for updating the arrays.
var values = [{ code: 200, message: 'a' }, { code: 300, message: 'b' }, { code: 200, message: 'c' }, { code: 400, message: 'd' }, { code: 200, message: 'e' }],
hash = Object.create(null),
data = [],
label = [];
values.forEach(function (o) {
if (o.code in hash) {
data[hash[o.code]] += 1;
return;
}
hash[o.code] = data.push(1) - 1;
label.push(o.code);
});
console.log(data);
console.log(label);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 52
This look like you want some object which is like an array and can have key-value. I recommend using Map
have a look here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
with this you could make this with one loop and receive the correct result you needed
Upvotes: 1
Reputation: 440
A little more clean using a newer version of Javascript, should work the same though. Check it out.
const objs = [{
code: 200,
message: 'a'
},
{
code: 300,
message: 'b'
},
{
code: 200,
message: 'c'
},
{
code: 400,
message: 'd'
},
{
code: 200,
message: 'e'
},
];
const data = [];
const labels = [];
objs.forEach(obj => {
if (labels.indexOf(obj.code) < 0) {
labels.push(obj.code);
data.push(1);
} else {
const index = labels.indexOf(obj.code);
data[index] ++;
}
});
console.log('data', data);
console.log('labels', labels);
Upvotes: 1