Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

JavaScript recursive function loops infinitely and didn't get the right answer

I am writing a recursive function to find out the item which has the same id as I pass to the function.

As you can see that each object item has an id property and the item also has a sub_categories property which is an array contains some other objects or an empty array.

const arr = [
    {
        "id": 1013,
        "code": "CAT1",
        "name": {
            "en": "TOP 1",
            "fr": "TOP 1"
        },
        "_name": "TOP 1",
        "level": 1,
        "sub_categories": [
            {
                "id": 1016,
                "code": "SUB1",
                "name": {
                    "en": "Child 1",
                    "fr": "Child 1"
                },
                "_name": "Child 1",
                "level": 2,
                "sub_categories": [
                    {
                        "id": 1017,
                        "code": "SUB11",
                        "name": {
                            "en": "Child 2",
                            "fr": "Child 2"
                        },
                        "_name": "Child 2",
                        "level": 3,
                        "sub_categories": [
                            {
                                "id": 1018,
                                "code": "SUB111",
                                "name": {
                                    "en": "Child 3",
                                    "fr": "Child 3"
                                },
                                "_name": "Child 3",
                                "level": 4,
                                "sub_categories": [
                                    {
                                        "id": 1019,
                                        "code": "SUB21",
                                        "name": {
                                            "en": "Child 4",
                                            "fr": "Child 4"
                                        },
                                        "_name": "Child 4",
                                        "level": 5,
                                        "sub_categories": []
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        "id": 1014,
        "code": "CAT2",
        "name": {
            "en": "TOP 2",
            "fr": "TOP 2"
        },
        "_name": "TOP 2",
        "level": 1,
        "sub_categories": [
            {
                "id": 1020,
                "code": "SUB22",
                "name": {
                    "en": "Child 1",
                    "fr": "Child 1"
                },
                "_name": "Child 1",
                "level": 2,
                "sub_categories": []
            }
        ]
    },
    {
        "id": 1015,
        "code": "CAT3",
        "name": {
            "en": "TOP 3",
            "fr": "TOP 3"
        },
        "_name": "TOP 3",
        "level": 1,
        "sub_categories": []
    }
]
const arrFilter = (targetId) => {
        let res = null;
        for(let y = 0; y < arr.length; y++) {
          if (arr[y].id === targetId) {
          res = arr[y];
       } else if(arr[y].sub_categories.length) {
          res = arrFilter(arr[y].sub_categories, targetId)
       }
      
       if(res !== null) return res;
    }
}

console.log(arrFilter(1017))

When I pass the id 1017, it throws an error said Maximum call stack size exceeded, it seems loops infinitely. Anyone know why my code loops infinitely?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You’re using arr in your function to search for the item, however, if you call the function for the second time, you’re still using arr.

You’ll need to pass the array itself to the function so the second (recursive) time you only search that part:

const arr = [{"id": 1013, "code": "CAT1", "name": {"en": "TOP 1", "fr": "TOP 1"}, "_name": "TOP 1", "level": 1, "sub_categories": [{"id": 1016, "code": "SUB1", "name": {"en": "Child 1", "fr": "Child 1"}, "_name": "Child 1", "level": 2, "sub_categories": [{"id": 1017, "code": "SUB11", "name": {"en": "Child 2", "fr": "Child 2"}, "_name": "Child 2", "level": 3, "sub_categories": [{"id": 1018, "code": "SUB111", "name": {"en": "Child 3", "fr": "Child 3"}, "_name": "Child 3", "level": 4, "sub_categories": [{"id": 1019, "code": "SUB21", "name": {"en": "Child 4", "fr": "Child 4"}, "_name": "Child 4", "level": 5, "sub_categories": [] } ] } ] } ] } ] }, {"id": 1014, "code": "CAT2", "name": {"en": "TOP 2", "fr": "TOP 2"}, "_name": "TOP 2", "level": 1, "sub_categories": [{"id": 1020, "code": "SUB22", "name": {"en": "Child 1", "fr": "Child 1"}, "_name": "Child 1", "level": 2, "sub_categories": [] } ] }, {"id": 1015, "code": "CAT3", "name": {"en": "TOP 3", "fr": "TOP 3"}, "_name": "TOP 3", "level": 1, "sub_categories": [] } ];

const arrFilter = (search, targetId) => {
        let res = null;
        for (let y = 0; y < search.length; y++) {
          if (search[y].id === targetId) {
          res = search[y];
       } else if(search[y].sub_categories.length) {
          res = arrFilter(search[y].sub_categories, targetId)
       }
      
       if(res !== null) return res;
    }
}

console.log(arrFilter(arr, 1017))

Slightly improved version could look something like:

const arr = [{"id": 1013, "code": "CAT1", "name": {"en": "TOP 1", "fr": "TOP 1"}, "_name": "TOP 1", "level": 1, "sub_categories": [{"id": 1016, "code": "SUB1", "name": {"en": "Child 1", "fr": "Child 1"}, "_name": "Child 1", "level": 2, "sub_categories": [{"id": 1017, "code": "SUB11", "name": {"en": "Child 2", "fr": "Child 2"}, "_name": "Child 2", "level": 3, "sub_categories": [{"id": 1018, "code": "SUB111", "name": {"en": "Child 3", "fr": "Child 3"}, "_name": "Child 3", "level": 4, "sub_categories": [{"id": 1019, "code": "SUB21", "name": {"en": "Child 4", "fr": "Child 4"}, "_name": "Child 4", "level": 5, "sub_categories": [] } ] } ] } ] } ] }, {"id": 1014, "code": "CAT2", "name": {"en": "TOP 2", "fr": "TOP 2"}, "_name": "TOP 2", "level": 1, "sub_categories": [{"id": 1020, "code": "SUB22", "name": {"en": "Child 1", "fr": "Child 1"}, "_name": "Child 1", "level": 2, "sub_categories": [] } ] }, {"id": 1015, "code": "CAT3", "name": {"en": "TOP 3", "fr": "TOP 3"}, "_name": "TOP 3", "level": 1, "sub_categories": [] } ];

const arrFilter = (search, targetId) => {
    for (const obj of search) {
        if (obj.id === targetId) {
            return obj;
        }
        if (obj.sub_categories.length > 0) {
            const tmp = arrFilter(obj.sub_categories, targetId);
            if (tmp) {
                return tmp;
            }
        }
    }
    return false;
}

console.log(arrFilter(arr, 1014))
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading