I have an array like this:
const array = [
{ id: 1, name: 'a1', props: [
{ name: 'b1', typeId: 1 },
{ name: 'b2', typeId: 1 },
{ name: 'b3', typeId: 5 },
{ name: 'b4', typeId: 5 },
] },
{ id: 2, name: 'a2', props: [
{ name: 'c1', typeId: 1 },
{ name: 'c2', typeId: 1 },
{ name: 'c3', typeId: 5 },
] },
{ id: 3, name: 'a3', props: [
{ name: 'd1', typeId: 5 },
{ name: 'd2', typeId: 5 },
] },
{ id: 4, name: 'a4', props: [
{ name: 'e1', typeId: 1 },
] }
];
I want to filter this array by prop's typeId attribute. For ex:
If typeId == 5
, then it should return items that ids are 1, 2, 3 with only props' typeId equals 5. Like this:
filteredArray = [
{ id: 1, name: 'a1', props: [
{ name: 'b3', typeId: 5 },
{ name: 'b4', typeId: 5 },
] },
{ id: 2, name: 'a2', props: [
{ name: 'c3', typeId: 5 },
] },
{ id: 3, name: 'a3', props: [
{ name: 'd1', typeId: 5 },
{ name: 'd2', typeId: 5 },
] }
];
Or if typeId == 1
, then it should return items that ids are 1, 2, 4 with only props which typeId equals to 1. Like this:
filteredArray = [
{ id: 1, name: 'a1', props: [
{ name: 'b1', typeId: 1 },
{ name: 'b2', typeId: 1 },
] },
{ id: 2, name: 'a2', props: [
{ name: 'c1', typeId: 1 },
{ name: 'c2', typeId: 1 },
] },
{ id: 4, name: 'a4', props: [
{ name: 'e1', typeId: 1 },
] }
];
I wrote something like this, but it doesn't work as intended. It doesn't filter props arrays. Returns an item if it's props array have an item which typeId equals to typeId
.
let typeId = 1;
let filteredArray = array.filter(x => {
return x.props.some(y => {
return y.typeId == typeId;
});
});
CodePudding user response:
If you don't mind modifying the input data, you can do it with a forEach
:
array.forEach(
(elt) => elt.props = elt.props.filter((subElt) => subElt.typeId === 5)
)
Also, you might want to filter elements that have elt.props
empty :
const result = array.filter(elt => elt.props.length > 0)
CodePudding user response:
You can use map and filter by checking the typeId of the props
const array = [{
id: 1,
name: 'a1',
props: [{
name: 'b1',
typeId: 1
},
{
name: 'b2',
typeId: 1
},
{
name: 'b3',
typeId: 5
},
{
name: 'b4',
typeId: 5
},
]
},
{
id: 2,
name: 'a2',
props: [{
name: 'c1',
typeId: 1
},
{
name: 'c2',
typeId: 1
},
{
name: 'c3',
typeId: 5
},
]
},
{
id: 3,
name: 'a3',
props: [{
name: 'd1',
typeId: 5
},
{
name: 'd2',
typeId: 5
},
]
},
{
id: 4,
name: 'a4',
props: [{
name: 'e1',
typeId: 1
}]
}
];
const typeId = 5;
const result = array.map(({
id,
name,
props
}) => ({
id,
name,
props: props.filter(({
typeId: t
}) => t === typeId)
})).filter(({
props
}) => props.length);
console.log(result);
CodePudding user response:
You can use a filter
to get the wanted typeId
s then a reduce
on the main array to only keep the relevant items.
This method does not modify the original array.
const array = [
{ id: 1, name: 'a1', props: [
{ name: 'b1', typeId: 1 },
{ name: 'b2', typeId: 1 },
{ name: 'b3', typeId: 5 },
{ name: 'b4', typeId: 5 },
] },
{ id: 2, name: 'a2', props: [
{ name: 'c1', typeId: 1 },
{ name: 'c2', typeId: 1 },
{ name: 'c3', typeId: 5 },
] },
{ id: 3, name: 'a3', props: [
{ name: 'd1', typeId: 5 },
{ name: 'd2', typeId: 5 },
] },
{ id: 4, name: 'a4', props: [
{ name: 'e1', typeId: 1 },
] }
];
function filterBySubTypeId(baseArray, subprop, subpropValue) {
return baseArray.reduce((acc, val) => {
const props = val.props.filter(prop => prop[subprop] === subpropValue); // Keep track of filtered sub-properties
return props.length > 0 ? [...acc, {...val, props}] : acc; // Return the accumulator or the concatenated accumulator with a modified copy of the item
}, [])
}
console.log(filterBySubTypeId(array, 'typeId', 1))
console.log(filterBySubTypeId(array, 'typeId', 5))
console.log(filterBySubTypeId(array, 'typeId', 2)) // []