kb9
kb9

Reputation: 41

How to Filter a Nested Object with array of String

let products = [
    {
        name: "A",
        color: "Blue",
        size: {
            size1: 1,
            size2: 2,
            size3: 3,
        },
    },
    {
        name: "B",
        color: "Blue",
        size: {
            size1: 5,
            size2: 19,
            size3: 22,
        },
    },
    { name: "C", color: "Black", size: 70 },
    { name: "D", color: "Green", size: 50 },
];

filters = ['Blue','2']; 

the result must be the object that checks all strings in the array for example

 {
    name: "A",
    color: "Blue",
    size: {
        size1: 1,
        size2: 2,
        size3: 3,
    },
},

the research must be accepted whatever the value in the

Upvotes: 2

Views: 492

Answers (4)

Andrew Parks
Andrew Parks

Reputation: 8087

The function strings returns all nested strings within an object, converting any numbers to strings. Then, we just filter any product where the list of strings includes all necessary matches.

const products = [{"name":"A","color":"Blue","size":{"size1":1,"size2":2,"size3":3}},{"name":"B","color":"Blue","size":{"size1":5,"size2":19,"size3":22}},{"name":"C","color":"Black","size":70},{"name":"D","color":"Green","size":50}];
const filters = ['Blue','2'];
const subsetMatch=(a,s)=>s.every(i=>a.includes(i));
const strings=i=>typeof i==='object'?Object.values(i).flatMap(strings):i+'';
console.log(products.filter(i=>subsetMatch(strings(i),filters)));

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386540

You could take a closure over any of the search values and check if all of them are in the object or nested objest for filtering.

const
    has = f => {
        const check = o => o && typeof o === 'object'
            ? Object.values(o).some(check)
            : f === o;

        return check;
    },
    products = [{ name: "A", color: "Blue", size: { size1: 1, size2: 2, size3: 3 } }, { name: "B", color: "Blue", size: { size1: 5, size2: 19, size3: 22 } }, { name: "C", color: "Black", size: 70 }, { name: "D", color: "Green", size: 50 }],
    search = ['Blue', 2],
    result = products.filter(o => search.every(f => has(f)(o)));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Lajos Arpad
Lajos Arpad

Reputation: 76426

You can resolve the nest via using a stack in some manner, either by recursion or iteratively using a stack explicitly. Here's a recursive solution:

function getFiltered(obj, filters, found = null) {
    let outermostCall = (found === null);
    if (outermostCall) { //outermost call
        found = [];
        for (let index = 0; index < filters.length; index++) {
            found[index] = false;
        }
    }
    for (let key in obj) {
        if (typeof obj[key] === 'object') {
            let tempFound = getFiltered(obj[key], filters, found);
            for (let index = 0; index < found.length; index++) {
                if (tempFound[index]) found[index] = true;
            }
        } else {
            let foundIndex = -1;
            for (let index = 0; index < filters.length; index++) {
                if (filters[index] == obj[key]) {
                    foundIndex = index;
                    index = filters.length;
                }
            }
            if (foundIndex >= 0) {
                found[foundIndex] = true;
            }
        }
    }
    if (outermostCall) {
        return !found.filter(item => !item).length;
    }
    return found;
}

function getAllFiltered(array, filters) {
    let output = [];
    for (let obj of array) {
        if (getFiltered(obj, filters)) output.push(obj);
    }
    return output;
}

let products = [
    {
        name: "A",
        color: "Blue",
        size: {
            size1: 1,
            size2: 2,
            size3: 3,
        },
    },
    {
        name: "B",
        color: "Blue",
        size: {
            size1: 5,
            size2: 19,
            size3: 22,
        },
    },
    { name: "C", color: "Black", size: 70 },
    { name: "D", color: "Green", size: 50 },
];

let filters = ['Blue','2']; 

console.log(getAllFiltered(products, filters));

Upvotes: 1

Nuro007
Nuro007

Reputation: 177

You can use Array.every to check if all the filters are present in the object, if that's what you mean.

const products = [
  { name: "A", color: "Blue", size: { size1:1, size2:2, size3:3 } },
  { name: "B", color: "Blue", size: { size1:5, size2:19, size3:22 } },
  { name: "C", color: "Black", size: 70 },
  { name: "D", color: "Green", size: 50 },
];

const filters = ['Blue','2'];

const filtered = products.filter(product => {
  return Object.values(product).every(value => {
    return filters.includes(value);
  });
});

console.log(filtered);

Upvotes: 0

Related Questions