Reputation: 700
Here is my problem, I receive these kind of json data and I don't know in advance the keys (unknownProperty#) but the different objects in this data array have the same keys. What I need to do is to calculate the number of each level of alert (these levels are fixed). Here is what my end result should look like
var result = { unknownProperty1: { unknown: 0, ok: 2, warning: 0, ko: 1 },
unknownProperty2: { unknown: 0, ok: 0, warning: 2, ko: 1 },
unknownProperty3: { unknown: 3, ok: 0, warning: 0, ko: 0 },
unknownProperty4: { unknown: 0, ok: 0, warning: 3, ko: 0 },
unknownProperty5: { unknown: 0, ok: 0, warning: 2, ko: 1 } }
My script is working but I would like to know if there is any way to optimize/clean it with map/reduce/filter javascript function
const data = [
{
unknownProperty1: { alert: "ok", unusedItem1: "something" },
unknownProperty2: { alert: "warning", unusedItem1: "something" },
unknownProperty3: { alert: "unknown", unusedItem1: "something" },
unknownProperty4: { alert: "warning", unusedItem1: "something" },
unknownProperty5: { alert: "ko", unusedItem1: "something" }
},
{
unknownProperty1: { alert: "ok", unusedItem1: "something" },
unknownProperty2: { alert: "warning", unusedItem1: "something" },
unknownProperty3: { alert: "unknown", unusedItem1: "something" },
unknownProperty4: { alert: "warning", unusedItem1: "something" },
unknownProperty5: { alert: "warning", unusedItem1: "something" }
},
{
unknownProperty1: { alert: "ko", unusedItem1: "something" },
unknownProperty2: { alert: "ko", unusedItem1: "something" },
unknownProperty3: { alert: "unknown", unusedItem1: "something" },
unknownProperty4: { alert: "warning", unusedItem1: "something" },
unknownProperty5: { alert: "warning", unusedItem1: "something" }
}
];
var result = new Object();
var dataKeys = data.map(function(element) {
return Object.keys(element);
});
dataKeys[0].map(function(element) {
result[element] = { unknown: 0, ok: 0, warning: 0, ko: 0 };
});
//At this point the result is like what we expect but no calculation has been made yet
//We then increment the right values
data.map(function(element) {
for (var prop in element) {
if (Object.prototype.hasOwnProperty.call(element, prop)) {
// element correspond to the current object
// prop corresponds to the name of the key, for example 'unknownProperty1'
switch (element[prop].alert) {
case "ok":
result[prop].ok++;
break;
case "warning":
result[prop].warning++;
break;
case "unknown":
result[prop].unknown++;
break;
case "ko":
result[prop].ko++;
break;
default:
break;
}
}
}
});
console.log(result);
Upvotes: 3
Views: 1475
Reputation: 13703
Running late, but here is another example,
Full code (see console.log): https://stackblitz.com/edit/js-5rnwvv
Input data:
const data = [
{
unknownProperty1: { alert: "ok", unusedItem1: "something" },
unknownProperty2: { alert: "warning", unusedItem1: "something" },
unknownProperty3: { alert: "unknown", unusedItem1: "something" },
unknownProperty4: { alert: "warning", unusedItem1: "something" },
unknownProperty5: { alert: "ko", unusedItem1: "something" }
},
{
unknownProperty1: { alert: "ok", unusedItem1: "something" },
unknownProperty2: { alert: "warning", unusedItem1: "something" },
unknownProperty3: { alert: "unknown", unusedItem1: "something" },
unknownProperty4: { alert: "warning", unusedItem1: "something" },
unknownProperty5: { alert: "warning", unusedItem1: "something" }
},
{
unknownProperty1: { alert: "ko", unusedItem1: "something" },
unknownProperty2: { alert: "ko", unusedItem1: "something" },
unknownProperty3: { alert: "unknown", unusedItem1: "something" },
unknownProperty4: { alert: "warning", unusedItem1: "something" },
unknownProperty5: { alert: "warning", unusedItem1: "something" }
}
];
Code for output data:
const a = data.reduce((acc, x, i) => {
const keys = Object.keys(x);
keys.forEach((key, j) => {
const childKey = Object.keys(x[key])[0]; // only 'alert' key needed
if (acc.hasOwnProperty(keys[j])) {
// update existing key value pair
++acc[key][x[key][childKey]]
} else {
// add key value pair for the first time
acc = {
...acc,
[keys[j]]:
['unknown', 'warning', 'ko', 'ok'].reduce((ac, z) => ({ ...ac, [z]: x[key][childKey] === z ? 1 : 0 }), {})
}
}
})
return acc;
}, {})
Upvotes: 1
Reputation: 370689
Reduce into an object indexed by the unknownProperty_
keys, iterating over the inner objects and creating the appropriate key on the accumulator if it doesn't exist yet, and setting its value to { unknown: 0, ok: 0, warning: 0, ko: 0 }
. Then, on each iteration over an unknownProperty
object, just extract the alert
and increment the a[key][alert]
:
const data = [
{
unknownProperty1: { alert: "ok", unusedItem1: "something" },
unknownProperty2: { alert: "warning", unusedItem1: "something" },
unknownProperty3: { alert: "unknown", unusedItem1: "something" },
unknownProperty4: { alert: "warning", unusedItem1: "something" },
unknownProperty5: { alert: "ko", unusedItem1: "something" }
},
{
unknownProperty1: { alert: "ok", unusedItem1: "something" },
unknownProperty2: { alert: "warning", unusedItem1: "something" },
unknownProperty3: { alert: "unknown", unusedItem1: "something" },
unknownProperty4: { alert: "warning", unusedItem1: "something" },
unknownProperty5: { alert: "warning", unusedItem1: "something" }
},
{
unknownProperty1: { alert: "ko", unusedItem1: "something" },
unknownProperty2: { alert: "ko", unusedItem1: "something" },
unknownProperty3: { alert: "unknown", unusedItem1: "something" },
unknownProperty4: { alert: "warning", unusedItem1: "something" },
unknownProperty5: { alert: "warning", unusedItem1: "something" }
}
];
const dataByProperty = data.reduce((a, obj) => {
Object.entries(obj).forEach(([key, { alert }]) => {
if (!a[key]) {
a[key] = { unknown: 0, ok: 0, warning: 0, ko: 0 };
}
a[key][alert]++;
});
return a;
}, {});
console.log(dataByProperty);
Upvotes: 6
Reputation: 3130
Maybe a bit late, but this was my similar idea:
(NOTE: Avoid using let obj = new Object();
, use let obj = {}
instead)
const data = [
{
unknownProperty1: { alert: "ok", unusedItem1: "something" },
unknownProperty2: { alert: "warning", unusedItem1: "something" },
unknownProperty3: { alert: "unknown", unusedItem1: "something" },
unknownProperty4: { alert: "warning", unusedItem1: "something" },
unknownProperty5: { alert: "ko", unusedItem1: "something" }
},
{
unknownProperty1: { alert: "ok", unusedItem1: "something" },
unknownProperty2: { alert: "warning", unusedItem1: "something" },
unknownProperty3: { alert: "unknown", unusedItem1: "something" },
unknownProperty4: { alert: "warning", unusedItem1: "something" },
unknownProperty5: { alert: "warning", unusedItem1: "something" }
},
{
unknownProperty1: { alert: "ko", unusedItem1: "something" },
unknownProperty2: { alert: "ko", unusedItem1: "something" },
unknownProperty3: { alert: "unknown", unusedItem1: "something" },
unknownProperty4: { alert: "warning", unusedItem1: "something" },
unknownProperty5: { alert: "warning", unusedItem1: "something" }
}
];
let result = data.reduce((acc, val) => {
for (let i in val) {
if (!val.hasOwnProperty(i)) {
continue;
}
acc[i] || (acc[i] = {unknown: 0, ok: 0, warning: 0, ko: 0});
acc[i][val[i].alert]++;
}
return (acc);
}, {});
console.log(result);
Upvotes: 1