Как избавится от множественных циклов в многоуровневом объекте?

Нужно сменить статус сравнивая по ключу id и num

По ключам обращаться нельзя, они не известны, объект большой и значений много.

Ниже код работает, можно его как то сократить?

let id = 25;
let num = 104000;
let status = true;

let globalGroups = {
  5: {
    8: {
      2: {
        4: {
          id: 25,
          num: 104000,
          favorite: 0,
        }
      }
    },
  },
};

for (let i in globalGroups) {
  for (let j in globalGroups[i]) {
    for (let y in globalGroups[i][j]) {
      for (let u in globalGroups[i][j][y]) {
        if (parseInt(globalGroups[i][j][y][u].id) === id && globalGroups[i][j][y][u].num === num) {
          globalGroups[i][j][y][u].favorite = status ? 1 : 0;
          console.log(globalGroups[i][j][y][u].favorite);
        }
      }
    }
  }
}


Ответы (1 шт):

Автор решения: SwaD

Для обхода объектов с однотипной структурой данных лучше всего использовать рекурсию:

Рекурсия - когда функция вызывает саму себя

Ниже пример реализации рекурсивного поиска нужного элемента объекта:

function findsOne(arr) {
  for (let i in arr) {
    if (arr[i].hasOwnProperty('id') && arr[i].id === id && arr[i].num === num) {
      arr[i].favorite = status ? 1 : 0;
      return 1;
    } else {      
      const search = findsOne(arr[i]); // Вызываем себя
      if (search) return 1;
    }
  }
}

Полный пример:

let id = 25;
let num = 104000;
let status = true;

let globalGroups = {
  5: {
    8: {
      2: {
        4: {
          id: 25,
          num: 104000,
          favorite: 0,
        },
        41: {
          id: 26,
          num: 104000,
          favorite: 0,
        }
      }
    },
  },
  15: {
    18: {
      12: {
        14: {
          id: 25,
          num: 104000,
          favorite: 0,
        },
        42: {
          id: 25,
          num: 104000,
          favorite: 0,
        }
      }
    },
  },
};

// После первого найденного элемента, поиск остановится
function findsOne(arr) {
  for (let i in arr) {
    if (arr[i].hasOwnProperty('id') && arr[i].id === id && arr[i].num === num) {
      arr[i].favorite = status ? 1 : 0;
      return 1;
    } else {      
      const search = findsOne(arr[i]);
      if (search) return 1;
    }
  }
}
// Проверит все элементы в объекте и произведет замену 
// во всех элементах, подходящих под условие
findsOne(globalGroups);
console.log('ONE', globalGroups);

function findsAll(arr) {
  for (let i in arr) {
    if (arr[i].hasOwnProperty('id') && arr[i].id === id && arr[i].num === num) {
      arr[i].favorite = status ? 1 : 0;      
    } else {
      findsAll(arr[i]); // Вызываем себя
    }
  }
}

findsAll(globalGroups);
console.log('ALL', globalGroups);

→ Ссылка