Как преобразовать массив объекта во вложенный объект и наоборот в js
Массив объектов, в которых объекты иерархии хранятся в иерархии
имущество. Вложение объектов осуществляется на основе этой иерархии
[
{
"hierarchy" : ["obj1"],
"prop1":"value"
},
{
"hierarchy" : ["obj1","obj2"],
"prop2":"value",
"prop3":"value"
},
{
"hierarchy" : ["obj1","obj3"],
"prop4":"value",
"prop5":"value"
},
{
"hierarchy" : ["obj1","obj3", "obj4"],
"prop6":"value",
"prop7":"value",
"arr" :["val1", "val2"]
}
]
Ожидаемый вложенный объект, здесь удален ключ иерархии
{
"obj1":{
"prop1":"value",
"obj2" : {
"prop2":"value",
"prop3":"value"
},
"obj3":{
"prop4":"value",
"prop5":"value",
"obj4" : {
"prop6":"value",
"prop7":"value",
"arr" :["val1", "val2"]
}
}
}
}
Код, который я пробовал, но в строке 8 не удалось получить иерархию
var input = "nested array as above";
var output = {};
var globalTemp = output;
for(var i = 0 ; i<input.length ; i++){
var tempObj = input[i];
for(var key in tempObj){
if(key == "hierarchy"){
globalTemp = globlalTemp[tempObj[key]] = {};
}
}
}
console.log(globalTemp);
2 ответа
С более новой версией javascript вы могли бы использовать restparameters для пар ключ / значение требуемого значения и построить вложенную структуру, выполнив итерацию данного свойства иерархии, сохранив последнее свойство для назначения остальных свойств.
Исправленная часть getFlat
использует массив как стек без рекурсивных вызовов, чтобы предотвратить поиск в глубину, который сначала пытается получить наибольшее количество узлов глубины.
При запуске стек представляет собой массив с массивом фактического объекта и другой объект с пустым hierarchy
свойство с пустым массивом, потому что на самом деле ни один ключ объекта не известен.
Затем while
цикл проверяет, есть ли в стеке какие-то элементы, и если да, то он берет первый элемент стека и принимает назначение деструктуризации для получения объекта o
для возврата всех пар ключ / значение и другого объекта temp
с одним свойством hierarchy
с массивом пути к объекту o
,
push
флаг установлен в false
потому что только найденные свойства должны быть переданы позже в результирующий набор.
Теперь все свойства объекта проверены, и если
- ценность правдива (чтобы предотвратить
null
ценности), - тип является объектом (
null
это объект) и - свойство не является массивом
Затем обнаруживается новый объект для проверки. Этот объект помещается в стек с фактическим путем к нему.
Если нет, то значение найдено. Эта пара ключ / значение добавляется к temp
объект и флаг установлен в true
, для последующего нажатия на набор результатов.
Продолжайте с ключами объекта.
Позже проверь push
и толкать temp
объект с hierarchy
свойства и пользовательские свойства для набора результатов.
function getFlat(object) {
var stack = [[object, { hierarchy: [] }]],
result = [],
temp, o, push;
while (stack.length) {
[o, temp] = stack.shift();
push = false;
Object.keys(o).forEach(k => {
if (o[k] && typeof o[k] === 'object' && !Array.isArray(o[k])) {
stack.push([o[k], { hierarchy: temp.hierarchy.concat(k) }]);
} else {
temp[k] = o[k];
push = true;
}
});
push && result.push(temp);
}
return result;
}
var data = [{ hierarchy: ["obj1"], prop1: "value" }, { hierarchy: ["obj1", "obj2"], prop2: "value", prop3: "value" }, { hierarchy: ["obj1", "obj3"], prop4: "value", prop5: "value" }, { hierarchy: ["obj1", "obj3", "obj4"], prop6: "value", prop7: "value", arr: ["val1", "val2"] }],
object = data.reduce((r, { hierarchy, ...rest }) => {
var last = hierarchy.pop();
hierarchy.reduce((o, k) => o[k] = o[k] || {}, r)[last] = rest;
return r;
}, {}),
reclaimedData = getFlat(object);
console.log(object);
console.log(reclaimedData);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ты можешь использовать forEach
а также reduce
методы и внутри создают мелкую копию текущего объекта и удаляют hierarchy
имущество.
const data = [{"hierarchy":["obj1"],"prop1":"value"},{"hierarchy":["obj1","obj2"],"prop2":"value","prop3":"value"},{"hierarchy":["obj1","obj3"],"prop4":"value","prop5":"value"},{"hierarchy":["obj1","obj3","obj4"],"prop6":"value","prop7":"value","arr":["val1","val2"]}]
const result = {}
data.forEach(function(o) {
o.hierarchy.reduce(function(r, e) {
const clone = Object.assign({}, o);
delete clone.hierarchy
return r[e] = (r[e] || clone)
}, result)
})
console.log(result)