Related
I have an array of object which objects have array, and my problem is to filter objects based on values from a nested array.
const skus = [{
id: 1,
features: ["Slim"],
fields: [{
label: "Material",
value: "Material1"
}, ]
},
{
id: 2,
features: ["Cotton"],
fields: [{
label: "Material",
value: "Material2"
}, ]
},
{
id: 3,
features: ["Slim"],
fields: [{
label: "Material",
value: "Material3"
}, ]
}
];
output should be array based on features array, example:
const result = [{
id: 2,
features: ["Cotton"],
fields: [{
label: "Material",
value: "Material2"
},
{
label: "Type",
value: "Type2"
}
]
}]
I tried to using filter method, but it only works on on objects, but not on arrays nested in objects
const filteredData = skus.filter((item) =>
(item.fields.filter((field) => field.value === "Material2")).length !== 0
);
console.log(filteredData);
I think this is what you meant...
Well to understand better you must understand that Array is also a special object only in javascript so you can perform filter on objects or the nested objects too.
skus.filter((item,keys)=>{
return item['features'].includes("Cotton") // Pass the search term in includes
})
With this you can achieve your goal.
Let me know if this works for you.
I got the same output of the example you gave using :
skus.filter(sku => sku.features.includes("Cotton"));
I hope you can explain a bit more.
The Filter method allows you to delve deeper into an objects properties and perform comparisons.
const skus = [
{ id: 1, features: ["Slim"], fields: [{ label: "Material", value: "Material1" },] },
{ id: 2, features: ["Cotton"], fields: [{ label: "Material", value: "Material2" },] },
{ id: 3, features: ["Slim"], fields: [{ label: "Material", value: "Material3" },] }
];
let featureName = "Cotton"
let results = skus.filter(s => s.features.includes(featureName))
console.log(results);
I'm unsure where "{ label: "Type", value: "Type2" }" suddenly comes from in your results though?
I write this code, and got same output,
I using id and value from index features
const skus = [
{
id: 1,
features: ['Slim'],
fields: [
{
label: 'Material',
value: 'Material1'
}
]
},
{
id: 2,
features: ['Cotton'],
fields: [
{
label: 'Material',
value: 'Material2'
}
]
},
{
id: 3,
features: ['Slim'],
fields: [
{
label: 'Material',
value: 'Material3'
}
]
}
]
const result = skus.filter(
(item) => item.id === 2 && item.features[0] === 'Cotton'
)
console.log(result)
I want to compare 2 Arrays of Objects to find the object or objects which is not matched.
In the example below it should output {label: 'Addition', type: 'address', name: 'address_4', defaultValue: 'test'} as this Object is not matched.
const A = [{
label: 'Street Name',
type: 'address',
name: 'address_1',
defaultValue: 'test1'
},
{
label: 'House Number',
type: 'address',
name: 'address_2',
defaultValue: '1563l1'
},
{
label: 'Addition',
type: 'address',
name: 'address_3',
defaultValue: 'ABC684'
}
]
const B = [{
label: 'Street Name',
type: 'address',
name: 'address_1',
defaultValue: 'test1'
},
{
label: 'House Number',
type: 'address',
name: 'address_2',
defaultValue: '1563l1'
},
{
label: 'Addition',
type: 'address',
name: 'address_3',
defaultValue: 'ABC684'
},
{
label: 'Addition',
type: 'address',
name: 'address_4',
defaultValue: 'test'
}
]
const newSet = A;
const currentSet = B;
let difference = currentSet.filter((page1) => !newSet.find(page2 => page1.name === page2.name))
console.log(difference);
This does not work. It outputs an empty Array. What I'm doing wrong?
You might by comparing A with B which returns an empty array because there is no element in A which doesn't exist in B instead you should compare B with A.
Below code will return an empty array
const A = [
{
label: "Street Name",
type: "address",
name: "address_1",
defaultValue: "test1",
},
{
label: "House Number",
type: "address",
name: "address_2",
defaultValue: "1563l1",
},
{
label: "Addition",
type: "address",
name: "address_3",
defaultValue: "ABC684",
},
];
const B = [
{
label: "Street Name",
type: "address",
name: "address_1",
defaultValue: "test1",
},
{
label: "House Number",
type: "address",
name: "address_2",
defaultValue: "1563l1",
},
{
label: "Addition",
type: "address",
name: "address_3",
defaultValue: "ABC684",
},
{
label: "Addition",
type: "address",
name: "address_4",
defaultValue: "test",
},
];
let difference = A.filter((page1) => {
const result = B.find((page2) => page1.name === page2.name);
return !result;
});
console.log(difference);
You should compare B with A as:
const A = [
{
label: "Street Name",
type: "address",
name: "address_1",
defaultValue: "test1",
},
{
label: "House Number",
type: "address",
name: "address_2",
defaultValue: "1563l1",
},
{
label: "Addition",
type: "address",
name: "address_3",
defaultValue: "ABC684",
},
];
const B = [
{
label: "Street Name",
type: "address",
name: "address_1",
defaultValue: "test1",
},
{
label: "House Number",
type: "address",
name: "address_2",
defaultValue: "1563l1",
},
{
label: "Addition",
type: "address",
name: "address_3",
defaultValue: "ABC684",
},
{
label: "Addition",
type: "address",
name: "address_4",
defaultValue: "test",
},
];
let difference = B.filter((page1) => {
const result = A.find((page2) => page1.name === page2.name);
return !result;
});
console.log(difference);
If there is a case where you want to get the difference between two array then you can do as:
const [small, large] = A.length < B.length ? [A, B] : [B, A];
let difference = large.filter((page1) => {
const result = small.find((page2) => page1.name === page2.name);
return !result;
});
I have an array of objects that I want to filter by comparing a nested property to a search term.
For example:
let array = [
{
category: 15,
label: "Components",
value: "a614741f-7d4b-4b33-91b7-89a0ef96a099",
children: [
{
category: 1,
label: "Carousel1",
diId: 55946,
// as you can see there are many children nested array of object
children: [{ label: "nodatafoundmessage", value: "47d18fb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "be5e027b-9163-4cfb-8816-0c8e3b816086"
},
{
category: 2,
label: "Checkbox1",
diId: 193909,
children: [{ label: "datafound", value: "47d18sb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "045e8786-2165-4e1e-a839-99b1b0ceef57"
}
]
},
{
value: "4be22726-850c-4905-ab3b-039fcf607d55",
label: "Default",
children: [
{
category: 5,
defaultValueType: 1,
label: "Empty",
toType: "String",
value: "ebedb43f-4c53-491f-8954-d030321845cd"
},
{
category: 5,
defaultValueType: 2,
label: "Space",
toType: "String",
value: "2d0e1429-572b-4f21-9f83-3340bafff95a"
},
{
category: 5,
defaultValueType: 8,
label: "Current Username",
toType: "String",
value: "25f6b40a-33c7-4f17-b29d-99e8d1e4e33c"
},
{
category: 5,
defaultValueType: 9,
label: "Current Location",
toType: "Location",
value: "ed59da2f-318d-4599-9085-4d9d769a27d7"
}
]
},
{
category: 4,
label: "Fixed Value",
isFixed: true,
value: "28e90e3e-a20b-4499-9593-061a7d1e7bd6"
// as you can see there is no children in this object
}
]};
What I'm trying to achieve is if I search for 'nodata' for example my result should be
let array = [
{
category: 15,
label: "Components",
value: "a614741f-7d4b-4b33-91b7-89a0ef96a099",
children: [
{
category: 1,
label: "Carousel1",
diId: 55946,
// as you can see there are many children nested array of object
children: [{ label: "nodatafoundmessage", value: "47d18fb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "be5e027b-9163-4cfb-8816-0c8e3b816086"
}
]
}
];
Another option if I search for 'spa' my result should be
let array = [
{
value: "4be22726-850c-4905-ab3b-039fcf607d55",
label: "Default",
children: [
{
category: 5,
defaultValueType: 2,
label: "Space",
toType: "String",
value: "2d0e1429-572b-4f21-9f83-3340bafff95a"
}
]
}
];
I have been super confused and I decided to get some help. Thank you for your helps guys!
The following function should do the trick for you:
function searchData(dataArray, searchTerm) {
return dataArray.flatMap(obj => {
const objHasSearchTerm = Object.entries(obj)
.some(([key, value]) => key !== 'children' && String(value).toLowerCase().includes(searchTerm.toLowerCase()));
if (objHasSearchTerm && !obj.children) return [obj];
const matchedChildren = searchData(obj.children ?? [], searchTerm);
return objHasSearchTerm || matchedChildren.length > 0
? [{
...obj,
children: matchedChildren,
}]
: [];
})
}
It recursively goes through the data array, looks for any entries that have the specified search term, and if so, places it into the newly constructed object. It will preserve the nested shape of the object, which may or may not be what is needed. Feel free to tweak the algorithm to your own needs.
let allData = [
{
category: 15,
label: "Components",
value: "a614741f-7d4b-4b33-91b7-89a0ef96a099",
children: [
{
category: 1,
label: "Carousel1",
diId: 55946,
// as you can see there are many children nested array of object
children: [{ label: "nodatafoundmessage", value: "47d18fb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "be5e027b-9163-4cfb-8816-0c8e3b816086"
},
{
category: 2,
label: "Checkbox1",
diId: 193909,
children: [{ label: "datafound", value: "47d18sb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "045e8786-2165-4e1e-a839-99b1b0ceef57"
}
]
},
{
value: "4be22726-850c-4905-ab3b-039fcf607d55",
label: "Default",
children: [
{
category: 5,
defaultValueType: 1,
label: "Empty",
toType: "String",
value: "ebedb43f-4c53-491f-8954-d030321845cd"
},
{
category: 5,
defaultValueType: 2,
label: "Space",
toType: "String",
value: "2d0e1429-572b-4f21-9f83-3340bafff95a"
},
{
category: 5,
defaultValueType: 8,
label: "Current Username",
toType: "String",
value: "25f6b40a-33c7-4f17-b29d-99e8d1e4e33c"
},
{
category: 5,
defaultValueType: 9,
label: "Current Location",
toType: "Location",
value: "ed59da2f-318d-4599-9085-4d9d769a27d7"
}
]
},
{
category: 4,
label: "Fixed Value",
isFixed: true,
value: "28e90e3e-a20b-4499-9593-061a7d1e7bd6"
// as you can see there is no children in this object
}
];
function searchData(dataArray, searchTerm) {
return dataArray.flatMap(obj => {
const objHasSearchTerm = Object.entries(obj)
.some(([key, value]) => key !== 'children' && String(value).toLowerCase().includes(searchTerm.toLowerCase()));
if (objHasSearchTerm && !obj.children) return [obj];
const matchedChildren = searchData(obj.children ?? [], searchTerm);
return objHasSearchTerm || matchedChildren.length > 0
? [{
...obj,
children: matchedChildren,
}]
: [];
})
}
console.log('----- Search: nodata')
console.log(JSON.stringify(searchData(allData, 'nodata'), null, 2))
console.log('----- Search: spa')
console.log(JSON.stringify(searchData(allData, 'spa'), null, 2))
This question already has an answer here:
How do I filter an array of object containing an array of object itself?
(1 answer)
Closed 2 years ago.
const data = [
{ name: "name1", option: "option1", category: [{ id: 1, value: "national" }] },
{ name: "name2", option: "option2", category: [{ id: 2, value: "international" }] },
{ name: "name3", option: "option3", category: [{ id: 3, value: "sports" }] },
{ name: "name4", option: "option4", category: [{ id: 4, value: "entertainment" }] },
];
I would like to filter of this array value of category
// // console.log(data);
const result = data.filter(e => {
return e.category.filter(b => b.value === 'national')
})
// I want output like bellow
{ name: "name1", option: "option1", category: [{ id: 1, value: "national" }] },
I modify the code for multiple arrays in category:
const data = [
{ name: "name1", option: "option1", category: [{ id: 1, value: "national" }, {id: 1, value: "mundial" }]},
{ name: "name2", option: "option2", category: [{ id: 2, value: "international" }] },
{ name: "name3", option: "option3", category: [{ id: 3, value: "sports" }] },
{ name: "name4", option: "option4", category: [{ id: 4, value: "entertainment" }] },
];
var result = data.filter(x => x.category.some(y => y.value == "mundial"));
console.log(result);
I have multiple objects in an array. They each have a labelId assigned to them. If the label id is the same then I need to combine the objects by placing some of the values inside an array of the new combined object.
[
{
field: "legalName",
isOpened: false,
label: "Legal Name",
labelId: 1,
value: "John Doe"
},
{
field: "homeAddress1",
isOpened: false,
label: "Home Address",
labelId: 2,
value: "2343 Main Street"
},
{
field: "homeAddress2",
isOpened: false,
label: "Home Address",
labelId: 2,
value: "New York, NY"
}
]
What I want it to look like
[
{
isOpened: false,
label: "Legal Name",
labelId: 1,
values:
[
{field: "legalName", value: "John Doe"}
]
},
{
isOpened: false,
label: "Home Address",
labelId: 2,
values:
[
{field: "homeAddress1", value: "2343 Main Street"},
{field: "homeAddress2", value: "New York, NY"}
]
}
]
I am removing the field and value from the original object and placing it into an array of values for all objects regardless if they have the same labelId.
Code so far -
personalInfoArray.forEach(info => {
personalInfoArray.forEach(info2 => {
if ((info.labelId === info2.labelId) && (info.field !== info2.field)) {
info.values = [
{field: info.field, value: info.value},
{field: info2.field, value: info2.value}
]
}
})
})
I am looping through the same array twice in order to determine if the object has the same labelId, if success - create array. The issue is I'm not removing the properties and the other object still exists. Along with if they don't have the same labelId, nothing happens.
Thanks
This is an approach using the function Array.prototype.reduce to group the object by labelId and the function Object.values to extract the grouped objects.
let arr = [{ field: "legalName", isOpened: false, label: "Legal Name", labelId: 1, value: "John Doe" }, { field: "homeAddress1", isOpened: false, label: "Home Address", labelId: 2, value: "2343 Main Street" }, { field: "homeAddress2", isOpened: false, label: "Home Address", labelId: 2, value: "New York, NY" }],
result = Object.values(arr.reduce((a, {labelId, field, isOpened, label, value}) => {
(a[labelId] || (a[labelId] = {isOpened, label, labelId, values: []})).values.push({field, value});
return a;
}, Object.create(null)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }