Here is my question. I have an array of objects as shown below. Each object has a title and rows in it. rows
is also array of objects with risk
values like P1, P2, P3 etc. I want to filter and get only those rows whose risk
is equal to P1
. In some objects, there might be no risk with P1 at all. In that case, i want to ignore that object completely.
let data = [
{
"title": "QA",
"rows": [
{
"risk": "P3",
"Title": "Permission issue",
}
]
},
{
"title": "Prod",
"rows": [
{
"risk": "P5",
"Title": "Console log errors fix",
},
{
"risk": "P1",
"Title": "Server is in hung state",
}
]
}
]
I want the result as follows. As you can see the title QA
didnt have P1 at all. so i want to ignore that object as a whole.
{
"title": "Prod",
"rows": [
{
"risk": "P1",
"Title": "Server is in hung state",
}
]
}
]
I tried using this code. but the problem with this is that the title with QA gets added in the final output even though it doesnot have any P1 risk in it.
let result = input.map((obj) => ({
...obj,
rows: obj.rows.filter((row) => row.risk === "P1"),
}));
Can someone let me know how to filter the objects with P1 and skip the whole object if there are no P1 in it.
CodePudding user response:
You can build up a new list based on those which have rows with P1 risk.
data.reduce((acc, item) => {
const rows = item.rows.filter(it => it.risk === 'P1');
if (rows.length === 0) return acc;
return [...acc, {...item, rows }]
}, [])
CodePudding user response:
You can filter out those objects without risk === "P1" by using the function Array.prototype.filter
.
const data = [ { "title": "QA", "rows": [ { "risk": "P3", "Title": "Permission issue", } ] }, { "title": "Prod", "rows": [ { "risk": "P5", "Title": "Console log errors fix", }, { "risk": "P1", "Title": "Server is in hung state", } ] }],
result = structuredClone(data).filter(o => {
o.rows = o.rows.filter(({risk}) => risk === "P1");
return !!o.rows.length;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
I would skip the map entirely and only use a filter:
const result = data.filter((obj) => {
let includesP1 = false;
obj.rows.forEach((r) => {
if (r.risk === "P1") includesP1 = true;
});
return includesP1;
});
CodePudding user response:
Using reduce
you can filter out all non P1 risks.
const data = [
{ title: "QA", rows: [{ risk: "P3", Title: "Permission issue" }] },
{
title: "Prod",
rows: [
{ risk: "P5", Title: "Console log errors fix" },
{ risk: "P1", Title: "Server is in hung state" },
],
},
];
const result = data.reduce((acc, d) => {
const rows = d.rows.filter(({ risk }) => risk === "P1");
if (rows.length) {
acc.push({ ...d, rows });
}
return acc;
}, []);
console.log(result);
Another approach
You can also first filter the data that have at least one P1
risk and then from the filtered data remove all the non P1
risks.
const data = [
{ title: "QA", rows: [{ risk: "P3", Title: "Permission issue" }] },
{
title: "Prod",
rows: [
{ risk: "P5", Title: "Console log errors fix" },
{ risk: "P1", Title: "Server is in hung state" },
],
},
];
const result = data
.filter(({ rows }) => rows?.some(({ risk }) => risk === "P1"))
.map((d) => ({ ...d, rows: d.rows.filter(({ risk }) => risk === "P1") }));
console.log(result);
Relevant documentations:
- Array.prototype.reduce
- Array.prototype.filter
- Array.prototype.push
- Array.prototype.some
- Array.prototype.map
CodePudding user response:
This could be done as followed:
// function to check if a row has risk P1
const hasRiskP1 = (row) => { return row.risk === 'P1' };
// first filter out all rows which do not contain P1
// then filter out all entries which do not have any rows left
const result = data.map(entry => ({...entry, ...{rows: entry.rows.filter(hasRiskP1)}}))
.filter(entry => entry.rows.length);