Как преобразовать массив объекта во вложенный объект и наоборот в 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)

Другие вопросы по тегам