#javascript
#javascript
Вопрос:
Мне нужно глубоко отфильтровать объект категорий внутри массива, в массиве с несколькими объектами. При вызове API у меня будет этот массив объектов с вложенными категориями. Мне нужно отфильтровать каждый объект, если он содержит определенный идентификатор категории. Это JSON —
items_loop: [
{
ID: 1,
name: "Item A",
taxonomy: {
categories: [
{
name: "Book",
parent: 12,
taxonomy: "category",
},
{
name: "Cover",
parent: 4,
taxonomy: "category",
},
{
name: "Other",
parent: 15,
taxonomy: "category",
},
],
},
},
{
ID: 2,
name: "Item B",
taxonomy: {
categories: [
{
name: "Toys",
parent: 16,
taxonomy: "category",
},
{
name: "Book",
parent: 12,
taxonomy: "category",
},
{
name: "Other",
parent: 15,
taxonomy: "category",
},
],
},
},
{
ID: 3,
name: "Item C",
taxonomy: {
categories: [
{
name: "Ext",
parent: 6,
taxonomy: "category",
},
{
name: "Cover",
parent: 4,
taxonomy: "category",
},
{
name: "Other",
parent: 15,
taxonomy: "category",
},
],
},
},
]
Я хочу создать новый массив с объектом, который содержит только «родительский»: 15, но как я могу глубоко отфильтровать этот объект 3? Я пытался с этим, но это не работает
function findInObjArray(array, value) {
var found = []
// Helper to search obj for value
function findInObj(obj, value) {
return Object.values(obj).some((v) =>
// If v is an object, call recursively
typeof v == "object" amp;amp; v != "null"
? findInObj(v, value)
: // If string, check if value is part of v
typeof v == "string"
? v.indexOf(value) >= 0
: // Check numbers, make NaN == NaN
typeof v == "number"
? v === value || (isNaN(v) amp;amp; isNaN(value))
: // Otherwise look for strict equality: null, undefined, function, boolean
v === value
)
}
array.forEach(function (obj) {
if (findInObj(obj, value)) found.push(obj)
})
return found
}
Комментарии:
1.
condition ? val1 : val2 : val3
недопустимый синтаксис.
Ответ №1:
Вы имеете в виду что-то вроде этого — фильтровать массивы, которые находятся внутри объектов, которые находятся в вашем основном массиве? Вы можете повторять свой массив объектов по своему усмотрению и выполнять фильтрацию в цикле. Или используйте map
метод, как в примере ниже:
const obj = [{
ID: 1,
name: 'Item A',
taxonomy : {
categories : [{
name: "Book",
parent: 12,
taxonomy: "category",
},{
name: "Cover",
parent: 4,
taxonomy: "category",
},{
name: "Other",
parent: 15,
taxonomy: "category",
}]
}
},{
ID: 2,
name: 'Item B',
taxonomy : {
categories : [{
name: "Toys",
parent: 16,
taxonomy: "category",
},{
name: "Book",
parent: 12,
taxonomy: "category",
},{
name: "Other",
parent: 15,
taxonomy: "category",
}]
}
},{
ID: 3,
name: 'Item C',
taxonomy : {
categories : [{
name: "Ext",
parent: 6,
taxonomy: "category",
},{
name: "Cover",
parent: 4,
taxonomy: "category",
},{
name: "Other",
parent: 15,
taxonomy: "category",
}]
}
}];
// Map and filter nested content
const res = obj.map(a => {
a.taxonomy.categories = a.taxonomy.categories.filter(x => x.parent === 15);
return a;
});
// Log
console.log(res)
Или, если вы имеете в виду, что хотите отфильтровать свой основной массив, чтобы он содержал только объект, который имеет вложенный массив с некоторым значением — тогда это небольшая модификация предыдущего кода
const obj = [{
ID: 1,
name: 'Item A',
taxonomy : {
categories : [{
name: "Book",
parent: 12,
taxonomy: "category",
},{
name: "Cover",
parent: 4,
taxonomy: "category",
},{
name: "Other",
parent: 15,
taxonomy: "category",
}]
}
},{
ID: 2,
name: 'Item B',
taxonomy : {
categories : [{
name: "Toys",
parent: 16,
taxonomy: "category",
},{
name: "Book",
parent: 12,
taxonomy: "category",
},{
name: "Other",
parent: 15,
taxonomy: "category",
}]
}
},{
ID: 3,
name: 'Item C',
taxonomy : {
categories : [{
name: "Ext",
parent: 6,
taxonomy: "category",
},{
name: "Cover",
parent: 4,
taxonomy: "category",
},{
name: "Other",
parent: 15,
taxonomy: "category",
}]
}
}];
// Map and filter nested content
const res = obj.filter(a => {
if((a.taxonomy.categories.filter(x => x.parent === 6)).length > 0) return a;
});
// Log
console.log(res)
Ответ №2:
Приведенный ниже код должен возвращать массив только из item
объектов, в которых вложенный categories
массив был отфильтрован на совпадения.
Обратите внимание, что:
- Возвращаются только элементы, содержащие по крайней мере 1 соответствующую категорию (это означает, что если элемент не содержит никаких соответствующих категорий, он не будет присутствовать в выходных данных).
- В выходных данных присутствуют только соответствующие категории.
- Если
categoryFilterFunc
не возвращает совпадений по всем элементам и категориям, возвращаемое значение будет пустым массивом.
const obj = {
items_loop : [
{
ID: 1,
name: 'Item A',
taxonomy : {
categories : [
{
name: "Book",
parent: 12,
taxonomy: "category",
},
{
name: "Cover",
parent: 4,
taxonomy: "category",
},
{
name: "Other",
parent: 15,
taxonomy: "category",
},
]
}
},
{
ID: 2,
name: 'Item B',
taxonomy : {
categories : [
{
name: "Toys",
parent: 16,
taxonomy: "category",
},
{
name: "Book",
parent: 12,
taxonomy: "category",
},
{
name: "Other",
parent: 15,
taxonomy: "category",
},
]
}
},
{
ID: 3,
name: 'Item C',
taxonomy : {
categories : [
{
name: "Ext",
parent: 6,
taxonomy: "category",
},
{
name: "Cover",
parent: 4,
taxonomy: "category",
},
{
name: "Other",
parent: 15,
taxonomy: "category",
},
]
}
},
]
};
function filterCategories(someObject, categoryFilterFunc) {
return someObject.items_loop.reduce((accum, item) => {
const filtered = item.taxonomy.categories.filter(categoryFilterFunc);
if (filtered.length > 0) {
// Creating a deep copy will have some performance impact (depending on
// how many items and nested categories you need to iterate over)
// but seems advisable for nested objects. Up to you if you
// want to keep it.
const deepCopy = JSON.parse(JSON.stringify(item));
deepCopy.taxonomy.categories = filtered;
accum.push(deepCopy);
}
return accum;
}, []);
}
const matchingItems = filterCategories(obj, categoryObj => 15 === categoryObj.parent);
console.log(matchingItems);
Комментарии:
1. Спасибо, это работает, но в вызове Api у меня много объектов. Я предпочитаю использовать приведенный ниже метод map. Спасибо за помощь!