Robin Banks
Robin Banks

Reputation: 127

Filter array for objects with nested array that contains a specific string

I am trying to filter a large multi dimensional array, I know I can re build the array but I was wondering if there was a way of me filtering this array based on if the key "d" contains "d3.1"

   const arr = [
        {a:"a1",b:"b1",c:[{d:"d1.1",e:"e1.1"},{d:"d1.2",e:"e1.2"}]},
        {a:"a2",b:"b2",c:[{d:"d2.1",e:"e2.1"},{d:"d2.2",e:"e2.2"}]},
        {a:"a3",b:"b3",c:[{d:"d3.1",e:"e3.1"},{d:"d3.2",e:"e3.2"}]},
        {a:"a4",b:"b4",c:[{d:"d4.1",e:"e4.1"},{d:"d4.2",e:"e4.2"}]},
        {a:"a1",b:"b1",c:[{d:"d1.1",e:"e1.1"},{d:"d3.1",e:"e1.2"}]},
        {a:"a5",b:"b5",c:[{d:"d3.1",e:"e3.1"},{d:"d3.2",e:"e3.2"}]}
    ]

I have tried using .some and .filter but as it's an object within an array of objects I can't seem to get it to work.

My required output would be to have all objects where d contains "d3.1" for example:

output:

    [
       {a:"a3",b:"b3",c:[{d:"d3.1",e:"e3.1"},{d:"d3.2",e:"e3.2"}]},
       {a:"a1",b:"b1",c:[{d:"d1.1",e:"e1.1"},{d:"d3.1",e:"e1.2"}]},
       {a:"a5",b:"b5",c:[{d:"d3.1",e:"e3.1"},{d:"d3.2",e:"e3.2"}]}
    ]

Upvotes: 1

Views: 148

Answers (4)

Terry Lennox
Terry Lennox

Reputation: 30685

You could use a recursive approach to find matching array elements, creating a function like findMatch() that accepts a customizable predicate function.

This function could return true for exact matches or use regex expressions etc.

We'd then using this with Array.filter() to return the required result.

const arr = [ {a:"a1",b:"b1",c:[{d:"d1.1",e:"e1.1"},{d:"d1.2",e:"e1.2"}]}, {a:"a2",b:"b2",c:[{d:"d2.1",e:"e2.1"},{d:"d2.2",e:"e2.2"}]}, {a:"a3",b:"b3",c:[{d:"d3.1",e:"e3.1"},{d:"d3.2",e:"e3.2"}]}, {a:"a4",b:"b4",c:[{d:"d4.1",e:"e4.1"},{d:"d4.2",e:"e4.2"}]}, {a:"a1",b:"b1",c:[{d:"d1.1",e:"e1.1"},{d:"d3.1",e:"e1.2"}]}, {a:"a5",b:"b5",c:[{d:"d3.1",e:"e3.1"},{d:"d3.2",e:"e3.2"}]} ]

function findMatch(obj, predicate) {
    for(let k in obj) {
        if (obj[k] && typeof(obj[k]) === 'object') {
           if (findMatch(obj[k], predicate)) return true;
        } else if (predicate(k, obj[k])) {
            return true;
        }
    }
}

// Custom predicate, change as needed.
const predicate = (key, value) => key === 'd' && value === 'd3.1';
const result = arr.filter(el => findMatch(el, predicate));
console.log('Result:');
result.forEach(el => console.log(JSON.stringify(el)));
.as-console-wrapper { max-height: 100% !important; }

Upvotes: 1

Saad Rehman
Saad Rehman

Reputation: 79

You can use nested foreach to get your desired output, I have consoled both array(one containing the output you want and the other containing the indexes of those outputs)

values_ar = [];
index_ar = [];
arr.forEach((items, indexs)=>{
    const test = arr[indexs].c;
    test.forEach((item, index)=>{
        if(test[index].d == "d3.1"){
            values_ar.push(items)
            index_ar.push(indexs)
        }
    })
})
console.log(values_ar)
console.log(index_ar)

Hope that answers your question.

Upvotes: 0

some-user
some-user

Reputation: 4894

If you want to filter the array for elements with property c containing at least one element (i.e. .some(...)) with property d being equal to "d3.1" you can use this solution:

const arr = [
        {a:"a1",b:"b1",c:[{d:"d1.1",e:"e1.1"},{d:"d1.2",e:"e1.2"}]},
        {a:"a2",b:"b2",c:[{d:"d2.1",e:"e2.1"},{d:"d2.2",e:"e2.2"}]},
        {a:"a3",b:"b3",c:[{d:"d3.1",e:"e3.1"},{d:"d3.2",e:"e3.2"}]},
        {a:"a4",b:"b4",c:[{d:"d4.1",e:"e4.1"},{d:"d4.2",e:"e4.2"}]},
        {a:"a1",b:"b1",c:[{d:"d1.1",e:"e1.1"},{d:"d3.1",e:"e1.2"}]},
        {a:"a5",b:"b5",c:[{d:"d3.1",e:"e3.1"},{d:"d3.2",e:"e3.2"}]}
    ]
 
 const filtered = arr.filter(e => e.c.some(x => x.d == "d3.1"))
 
 console.log(filtered)

Otherwise, please specify your requirements closer...

Upvotes: 1

Syed Uzair Bukhari
Syed Uzair Bukhari

Reputation: 417

Here is a quick solution:

const arr = [
            {a:"a1",b:"b1",c:[{d:"d1.1",e:"e1.1"},{d:"d1.2",e:"e1.2"}]},
            {a:"a2",b:"b2",c:[{d:"d2.1",e:"e2.1"},{d:"d2.2",e:"e2.2"}]},
            {a:"a3",b:"b3",c:[{d:"d3.1",e:"e3.1"},{d:"d3.2",e:"e3.2"}]},
            {a:"a4",b:"b4",c:[{d:"d4.1",e:"e4.1"},{d:"d4.2",e:"e4.2"}]},
            {a:"a1",b:"b1",c:[{d:"d1.1",e:"e1.1"},{d:"d3.1",e:"e1.2"}]},
            {a:"a5",b:"b5",c:[{d:"d3.1",e:"e3.1"},{d:"d3.2",e:"e3.2"}]}
    ]
    
    
console.log(arr.filter(el => JSON.stringify(el).includes("d3.1")))

Upvotes: 2

Related Questions