I am trying to filter this json.
here is the json
const json = {
address: "fdqn",
pDet: [
{
pNam: "pnam1",
pMem: [
{
mIP: "1234", // search this string '1234'
gp: "gp1"
}, {
mIP: "567",
gp: "gp2"
}, {
mIP: "890",
gp: "gp3"
}
]
},
{
pNam: "pnam1",
pMem: [
{
mIP: "4567",
gp: "gp5"
}, {
mIP: "5674",
gp: "gp7"
}
]
}
]
}
I need to filter with mIP = "1234" and the final output should be.
const json = {
address: "fdqn",
pDet: [
{
pNam: "pnam1",
pMem: [
{
mIP: "1234",
gp: "gp1"
}
]
}
]
}
i tried with filter and some but seems i need to iterate inside the filter. any input will be appreciated
CodePudding user response:
Utilizing flatMap
to emulate the behavior of filter_map
in other languages, we could achieve the result like this:
const json = {address:"fdqn",pDet:[{pNam:"pnam1",pMem:[{mIP:"1234",gp:"gp1"},{mIP:"567",gp:"gp2"},{mIP:"890",gp:"gp3"}]},{pNam:"pnam1",pMem:[{mIP:"4567",gp:"gp5"},{mIP:"5674",gp:"gp7"}]}]};
const search = "1234";
const result = {
address: json.address,
// check if there is any match in this pMem
pDet: json.pDet.flatMap(({ pMem }) => pMem.some(({ mIP }) => mIP === search)
? [pMem.filter(({ mIP }) => mIP === search)] // if there is, return filtered array
: [] // otherwise, return nothing
),
};
console.log(result);
CodePudding user response:
You could use array.reduce()
and array.filter()
like this.
const json = { address: "fdqn", pDet: [{ pNam: "pnam1", pMem: [{ mIP: "1234", gp: "gp1" }, { mIP: "567", gp: "gp2" }, { mIP: "890", gp: "gp3" }] }, { pNam: "pnam1", pMem: [{ mIP: "4567", gp: "gp5" }, { mIP: "5674", gp: "gp7" }] } ] }
const newJSON = {
address: json.address,
pDet: json.pDet.reduce((newArr, obj) => {
const pMem = obj.pMem.filter(obj2 => obj2.mIP === '1234')
if (pMem.length) newArr.push({
pNam: obj.pNam,
pMem
})
return newArr
}, [])
}
console.log(newJSON)
In a function it could look like this:
const json = { address: "fdqn", pDet: [{ pNam: "pnam1", pMem: [{ mIP: "1234", gp: "gp1" }, { mIP: "567", gp: "gp2" }, { mIP: "890", gp: "gp3" }] }, { pNam: "pnam1", pMem: [{ mIP: "4567", gp: "gp5" }, { mIP: "5674", gp: "gp7" }] } ] }
function filterArray(jsonObj, searchStr) {
return {
address: json.address,
pDet: json.pDet.reduce((newArr, obj) => {
const pMem = obj.pMem.filter(obj2 => obj2.mIP === search)
if (pMem.length) newArr.push({
pNam: obj.pNam,
pMem
})
return newArr
}, [])
}
}
const newJSON = filterArray(json, '1234')
console.log( newJSON )
CodePudding user response:
Similar to the technique in the answer from @caTS, although a little more generic, I used a filterMap
. In my case, I grabbed a reusable function I have handy. It looks like this:
const filterMap = (f, m) => (xs) => xs .flatMap (x => f (x) ? [m (x)] : [])
const searchMIP = ({pDet, ...rest}, query) => ({
...rest,
pDet: filterMap (
({pMem}) => pMem .some (({mIP}) => mIP == query),
({pMem, ...rest}) => ({...rest, pMem: pMem .filter (({mIP}) => mIP == query)})
) (pDet)
})
const obj = {address: "fdqn", pDet: [{pNam: "pnam1", pMem: [{mIP: "1234", gp: "gp1"}, {mIP: "567", gp: "gp2"}, {mIP: "890", gp: "gp3"}]}, {pNam: "pnam1", pMem: [{mIP: "4567", gp: "gp5"}, {mIP: "5674", gp: "gp7"}]}]}
console .log (searchMIP (obj, '1234'))
But I wasn't really happy with that, as one of the usual advantages of filterMap
is that it only scans the list once. But here, we do it in the filter section, using some
and again in the map section using filter
.
So here's a slightly different approach, still using flatMap
to do something similar, but filtering only once and using the length
of the result to decide whether we're keeping the object at all:
const searchMIP = ({pDet, ...rest}, query) => ({
...rest,
pDet: pDet .flatMap (
({pMem, kids = pMem .filter (({mIP}) => mIP == query), ...rest}) => kids .length ? [({
...rest,
pMem: pMem .filter (({mIP}) => mIP == query)
})] : []
)
})
const obj = {address: "fdqn", pDet: [{pNam: "pnam1", pMem: [{mIP: "1234", gp: "gp1"}, {mIP: "567", gp: "gp2"}, {mIP: "890", gp: "gp3"}]}, {pNam: "pnam1", pMem: [{mIP: "4567", gp: "gp5"}, {mIP: "5674", gp: "gp7"}]}]}
console .log (searchMIP (obj, '1234'))
.as-console-wrapper {max-height: 100% !important; top: 0}
This is more similar to the answer from user @Ludolfyn, but without the mutable accumulator, and again, slightly more generic.