0

I have two arrays, I need to filter this based on name.

const arr1 = ["Saab", "Volvo", "BMW", "Car3", "Car2", "Van", "Bus"];
const arr2 = [
    {
        name: "Saab",
        url: "saab/"
    },
    {
        name: "Volvo",
        url: "volvo/",
        children:[
            {
                name: "Van",
                url: "van/"
            },
            {
                name: "Bus",
                url: "bus/"
            },
        ]
    },
    {
        name: "BMW",
        url: "bmw/"
    },
    {
        name: "SUV",
        url: "suv/",
        children:[
            {
                name: "Car1",
                url: "car1/"
            },
            {
                name: "Car2",
                url: "car2/"
            },
            {
                name: "Car3",
                url: "car3/"
            },
        ]
    }
]

I tried with this code. const result = arr2.filter((item) => arr1.includes(item.name);

This code working fine but it does not check children object in arr2, I need to check based on the arr1 values and if I have children object I need to check that name also. For example: name SUV is in the arr1 but car1 and car2 value are not in arr1 that time I need to remove that SUV object.

My output should be:

[
    {
        name: "Saab",
        url: "saab/"
    },
    {
        name: "Volvo",
        url: "volvo/",
        children:[
            {
                name: "Van",
                url: "van/"
            },
            {
                name: "Bus",
                url: "bus/"
            },
        ]
    },
    {
        name: "BMW",
        url: "bmw/"
    },
]

How can I do this using javascript, is it possible to do in es6?

3 Answers 3

1

You can use another filter function to check children inside the filter function for that.

Explanation:

  • checking item and item.length to be sure children exists and is not empty (you can remove the second one if not necessary, but it's safer because in most cases it assures that children is an array and that .every will not throw error)
  • .every and .includes test if all children are in arr1
  • for the second part of the alternative with || it is not executed if first part is true
  • in this second part, you have to test !item.children because if first alternative fails on children, it would fallback on the result of arr1.includes(item.name) and "SUV" would come back in the result

const arr1 = ["Saab", "Volvo", "BMW", "SUV", "Car3", "Van", "Bus"];
const arr2 = [
    {
        name: "Saab",
        url: "saab/"
    },
    {
        name: "Volvo",
        url: "volvo/",
        children:[
            {
                name: "Van",
                url: "van/"
            },
            {
                name: "Bus",
                url: "bus/"
            },
        ]
    },
    {
        name: "BMW",
        url: "bmw/"
    },
    {
        name: "SUV",
        url: "suv/",
        children:[
            {
                name: "Car1",
                url: "car1/"
            },
            {
                name: "Car2",
                url: "car2/"
            },
            {
                name: "Car3",
                url: "car3/"
            },
        ]
    }
];

const result = arr2.filter( (item) => ( (item.children && item.children.length && item.children.every(v => arr1.includes(v.name))) || (!item.children && arr1.includes(item.name)) ) );

console.log(result);

EDIT: fixed code to meet requirements

EDIT2: turned into a pure ES6 answer, old fashioned not necessary now

Sign up to request clarification or add additional context in comments.

11 Comments

thanks for posting I no need to return the "SUV" object itself
Yes give me the time to edit, I misunderstood your requirements (the explanation was a bit imprecise)
@techie18 edited the answer. I would usually use a regular for loop to optimize by exiting the loop if a children is not found though
Sounds a bit strange to set i=l to end the for loop. Instead, why don't you use break?
A personal habit I guess, never liked break keyword, if there is extra code in the second part of the for declaration, I'd prefer it to be executed
|
0

you can use foreach on result and check the items value by last method (filter your nested array).

Comments

0

Please try this.

res = arr2.filter(item2 => (arr1.findIndex(item1 => item2['name'] == item1) > -1))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.