Reputation: 127
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
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
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
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
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