Home > Net >  How to filter object array based on various values within a json object
How to filter object array based on various values within a json object

Time:07-13

Given the following array of objects:

let list = [
    {id: 100, desc: 'Apple'},
    {id: 555, desc: 'Banana'},
    {id: 110, desc: 'Orange'},
    {id: 120, desc: 'Strawberry'}
]

and the following:

let myObj = {
    "res": {
        "myId": 555,
        "allIds": [
            {
                "subId": 100
            },
            {
                "subId": 120
            }
        ]
    }
}

I need to filter the list array above so that it doesn't include the myId value and any of the subId values within the allIds array.

So based on this requirement after filtering, I expect to only see the following remaining value within the list array, i.e.:

let list = [
    {id: 110, desc: 'Orange'}
]

as id: 110 doesn't equal myId and doesn't exist within the allIds array.

I tried the following which works for just myId:

let filteredArr = {list.filter((el) => el.id !== myObj.res.myId)}

but unsure how to also exclude/filter the subId's within the allIds array as well?

CodePudding user response:

I tried the following which works for just myId:

let filteredArr = {list.filter((el) => el.id !== myObj.res.myId)}

but unsure how to also exclude/filter the subId's within the allIds array as well?

First, those {...} around list.filter(...) don't belong there. The { after a = starts an object initializer, but that's not valid content for an object initializer.

Use && ("and") and then myObj.res.allIds.every to see if the subId of every element in myObj.res.allIds is not a match for el.id:

let filteredArr = list.filter(
    (el) => el.id !== myObj.res.myId && myObj.res.allIds.every(({ subId }) => subId !== el.id)
);

Live Example:

let list = [
    { id: 100, desc: "Apple" },
    { id: 555, desc: "Banana" },
    { id: 110, desc: "Orange" },
    { id: 120, desc: "Strawberry" },
];

let myObj = {
    res: {
        myId: 555,
        allIds: [
            {
                subId: 100,
            },
            {
                subId: 120,
            },
        ],
    },
};

let filteredArr = list.filter(
    (el) => el.id !== myObj.res.myId && myObj.res.allIds.every(({ subId }) => subId !== el.id)
);
console.log(filteredArr);

That's assuming that myObj.res.allIds is fairly short, so it's okay to re-traverse it for (nearly) every element of list. If it's not short, you might want to create a Set containing all of the disallowed id valuse (myObj.res.myId and the subId values) first, since lookup time for the has method of a Set is guaranteed to be sublinear (whereas every will be linear):

const disallowed = new Set([
    myObj.res.myId,
    ...myObj.res.allIds.map(({subId}) => subId),
]);
let filteredArr = list.filter((el) => !disallowed.has(el.id));

Live Example:

let list = [
    { id: 100, desc: "Apple" },
    { id: 555, desc: "Banana" },
    { id: 110, desc: "Orange" },
    { id: 120, desc: "Strawberry" },
];

let myObj = {
    res: {
        myId: 555,
        allIds: [
            {
                subId: 100,
            },
            {
                subId: 120,
            },
        ],
    },
};

const disallowed = new Set([
    myObj.res.myId,
    ...myObj.res.allIds.map(({subId}) => subId),
]);
let filteredArr = list.filter((el) => !disallowed.has(el.id));
console.log(filteredArr);

CodePudding user response:

You'll need to collate a list of ids that you want to filer from your myObj object and simply filter the list. Something like this...

const blackList = [ myObj.res.myId, ...myObj.res.allIds.map(o => o.subId) ]
const filteredArr = list.filter(o => !blackList.includes(o.id))

console.log(filteredArr)
  • Related