Выполните итерацию по глубоко вложенному объекту JavaScript и получите путь к ключам

#javascript #node.js #object

Вопрос:

Как можно выполнить итерацию через глубоко вложенный объект, извлекая путь к каждому ключу, содержащему значение.

Демонстрационный объект ввода

 {
  nested: { 
    nested2: { 
      nested3: '123' 
    },
    nested4: '456' 
  }
}
 

желаемый результат

 nested.nested2.nested3
nested.nested4
 

Ответ №1:

Вы можете рекурсивно посещать узлы, сохраняя ссылку на стек. Я изменил объект, добавив пример массива.

Я просто соединяю путь разделителями точек, а затем преобразую цифровые клавиши в обозначения в скобках, используя следующее регулярное выражение.

/(?:.)(d )(?![a-z_])/ig

Я объединил несоответствующую группу (начинается с точки) и с отрицательным заголовком (не предшествует букве).

В качестве альтернативы можно использовать следующее выражение:

/(?:.)(d )(?=.)/g

Я заменил отрицательный внешний вид на положительный. Я, по сути, перевернул выражение, что может быть лучше для данной ситуации.

 const obj = {
  nested: { 
    nested2: [
      { nested3: '123' },
      { nested4: '456' }
    ],
    nested5: '789' 
  }
};

const visitNodes = (obj, visitor, stack = []) => {
  if (typeof obj === 'object') {
    for (let key in obj) {
      visitNodes(obj[key], visitor, [...stack, key]);
    }
  } else {
    visitor(stack.join('.').replace(/(?:.)(d )(?![a-z_])/ig, '[$1]'), obj);
  }
}

visitNodes(obj, (path, value) => console.log(`${path} = ${value}`)); 

Комментарии:

1. Большое вам спасибо, я не мог уследить за стеком в том, что написал.

2. @GregManiak Я исправил флаги регулярных выражений и обновил/исправил некоторые формулировки.

Ответ №2:

Вот краткое решение с использованием Array.reduce :

 const obj = {
  nested: {
    nested2: {
      nested3: '123'
    },
    nested4: '456'
  }
};

const r = (e, c = "") => Object.keys(e).reduce((t, y) => Array.isArray(e[y]) ? t : "object" == typeof e[y] ? [...t, ...r(e[y], c   y   ".")] : [...t, c   y], []);

var s = r(obj)
console.log(s); 

Комментарии:

1. Прекрасный синтаксис — и такой интуитивно понятный 😉

2. Я бы тоже подошел к этому таким образом, но для некоторых переменных и некоторых разрывов строк можно было бы использовать более длинные имена.

Ответ №3:

Вам придется выполнять рекурсию по путям объекта, пока он не достигнет чего-то, что не является объектом, и в этот момент он должен зарегистрировать путь до этой точки.

 var x = {
  nested: {
    nested2: {
      nested3: '123'
    },
    nested4: '456'
  }
};


const printPaths = (obj, parentPath) => {
  if (typeof obj === "object" amp;amp; !Array.isArray(obj)) {
    const layerKeys = Object.keys(obj);
    for (const ky of layerKeys) {
      const newKey = parentPath ? `${parentPath}.${ky}` : ky;
      printPaths(obj[ky], newKey);
    }
  } else if (parentPath) {
    console.log(parentPath);
  }
};

printPaths(x);