@DaveGarrow

Как получить количество вхождений ключа в объекте глубокой вложенности (вперемешку с массивами)?

Нужно количество всех вхождений ключа 'isTaskDone' в объекте.
Но объект может быть абсолютно любой вложенности и содержать в себе массивы, где тоже могут быть объекты с нужным ключом и т. д.

Например:
{
		list: [
			{
				isTaskDone:  false,
			},
		],
		facilities: {
			bigViews: {
				isTaskDone: false,
				views: [
					{
						isTaskDone:  false,: false,
					},
				],
			},
			facilitiesList: [
				{	
					isTaskDone: false,
				},
				{	
					isTaskDone: false,
				},
				{	
					isTaskDone: false,
					repairList: [
						{
							isTaskDone:  false,
						},
					],
				},
			],
		}
}
  • Вопрос задан
  • 20 просмотров
Решения вопроса 1
Aleksandr-JS-Developer
@Aleksandr-JS-Developer
Бери и делай
Можно создать рекурсивную функцию, которая "проваливается" в глубину объекта и проверяет все ключи

Примерно вот так: JSFiddle
код
const obj = {
  list: [{
    isTaskDone: false,
  }, ],
  facilities: {
    bigViews: {
      isTaskDone: false,
      views: [{
        isTaskDone: false,
        some: false,
      }, ],
    },
    facilitiesList: [{
        isTaskDone: false,
      },
      {
        isTaskDone: false,
      },
      {
        isTaskDone: false,
        repairList: [{
          isTaskDone: false,
        }, ],
      },
    ],
  }
}


const calculeFields = (obj, field = '') => {
	let count = 0;

	const rec = obj => {
  	for( let key in obj ){
    	if( key === field ){
      	count++;
      }
    	if( typeof obj[key] === 'object' ){
      	rec( obj[key] )
      }
    }
  }
  rec( obj );
  return count;
}

console.log( calculeFields( obj, 'isTaskDone' ) );


UPD
Забыл добавить, что если в объекте есть циркулярные ссылки (какой-то дочерний объект ссылается на своего родителя), то этот код выпадет в бесконечный цикл. Решается всё это обычной маркировкой и проверкой перед рекурсией.
Вот так
const obj = {
  list: [{
    isTaskDone: false,
  }, ],
  facilities: {
    bigViews: {
      isTaskDone: false,
      views: [{
        isTaskDone: false,
        some: false,
      }, ],
    },
    facilitiesList: [{
        isTaskDone: false,
      },
      {
        isTaskDone: false,
      },
      {
        isTaskDone: false,
        repairList: [{
          isTaskDone: false,
        }, ],
      },
    ],
  }
}

obj.clone = obj; // вот эта строчка создаст циркулярную ссылку внутри объекта.


const marks = {
	markKey: 'temp_mark_411212',
  marksArr: []
}

const calculeFields = (obj, field = '') => {
	let count = 0;

	const rec = obj => {
  	if( obj[marks.markKey] ){
  		return;
  	} else {
    	obj[marks.markKey] = true;
      marks.marksArr.push( obj );
    }
  
  	for( let key in obj ){
    	if( key === field ){
      	count++;
      }
    	if( typeof obj[key] === 'object' ){
      	rec( obj[key] )
      }
    }
  }
  rec( obj );
  
  marks.marksArr.forEach( item => delete item[marks.markKey] );
  return count;
}

console.log( calculeFields( obj, 'isTaskDone' ) );
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы