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

Time:10-12

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?

CodePudding user response:

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))

  • Related