Конвертировать массив объектов в глубоко вложенный объект в зависимости от конкретного ключа - PullRequest
2 голосов
/ 06 мая 2019

У меня есть массив объектов.

{
  c1 : ["a1", "c2"],
  c2 : ["b1"],
  c3: ["d1"], 
  b1: ["e"]
  d1: ["k"]
}

Мне нужно, чтобы объект был упорядочен по иерархии.например,

{ 
   c1: [{a1: null}, {
           c2: [{ 
              b1: "e"
           }]
       }],
   c3: [{ d1: "k" }]
}

Обратите внимание, что мы можем опустить массив в последний (самый глубокий) ключ: пара значений .Это то, что я пробовал до сих пор.

for (v in hash){ 
   hash[v].forEach(function(ar){
    if(hash[ar]){
        if (new_hash[v] == undefined){
            new_hash[v] = []
        }
        new_hash[v].push({[ar] : hash[ar]})
    }
   })
}

Я думаю, что эта проблема требует динамического программирования (рекурсия с сохранением состояния), в котором я не очень хорош.Пожалуйста, помогите.

Ответы [ 3 ]

1 голос
/ 06 мая 2019

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

Чтобы преодолеть проблему узлов без дочерних элементов, я добавил пустой массив, потому что исходная разыскиваемая структура имеет либо null, либо никаких дочерних элементов вообще, как этот узел

{ b1: "e" }

где как с нулевым маркером должно быть

{ b1: [{ e: null }] }

Это решение содержит пустой массив, который можно заменить любым другим значением.

{ b1: [{ e: [] }] }

var hash = { c1: ["a1", "c2"], c2: ["b1"], c3: ["d1"], b1: ["e"], d1: ["k"] },
    keys = Object.keys(hash),
    parents = new Set(keys),
    temp = {},
    tree ;

keys.forEach(k => hash[k].forEach(t => {
    parents.delete(t);
    temp[k] = temp[k] || [];
    temp[t] = temp[t] || [];
    if (!temp[k].some(o => t in o)) temp[k].push({ [t]: temp[t] });
}));

tree = Object.assign({}, ...Array.from(parents, k => ({ [k]: temp[k] })));

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 06 мая 2019

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

const data = {
  c1: ["a1", "c2"],
  c2: ["b1"],
  c3: ["d1"],
  b1: ["e"],
  d1: ["k"]
}

function find(obj, key) {
  let result = null
  for (let i in obj) {
    if (obj[i] === key || i === key) {
      result = obj
    }

    if (!result && typeof obj[i] == 'object') {
      result = find(obj[i], key)
    }
  }
  return result
}

function nest(data) {
  return Object.keys(data).reduce((r, e) => {
    const match = find(r, e);
    if (match) {
      if (!match[e]) match[e] = []
      match[e].push({
        [data[e]]: null
      })
    } else {
      data[e].forEach(el => {
        if (!r[e]) r[e] = [];
        r[e].push({
          [el]: null
        })
      })
    }
    return r;
  }, {})
}

const result = nest(data);
console.log(result)
0 голосов
/ 06 мая 2019

Вы можете просмотреть этот список родителей и детей без рекурсии, чтобы получить дерево.

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

const data = {
  c1: ["a1", "c2"],
  c2: ["b1"],
  c3: ["d1"],
  b1: ["e"],
  d1: ["k"],
};

// Generate a hash of nodes, mapping them to their children and parents.
const nodes = {};
Object.entries(data).forEach(([parentId, childIds]) => {
  const parent = (nodes[parentId] = nodes[parentId] || {
    id: parentId,
    children: [],
  });
  childIds.forEach(childId => {
    const child = (nodes[childId] = nodes[childId] || {
      id: childId,
      children: [],
    });
    parent.children.push(child);
    child.parent = parent;
  });
});


// Filter in only the nodes with no parents
const rootNodes = {};
Object.values(nodes).forEach(node => {
  // TODO: transform the {id, children, parent} nodes to whichever format you require
  if (!node.parent) rootNodes[node.id] = node;
});

rootNodes будет выглядеть

{
  c1: {
    id: 'c1',
    children: [
      { id: 'a1', children: [], parent: ... },
      {
        id: 'c2',
        children: [
          {
            id: 'b1',
            children: [ { id: 'e', children: [], parent: ... } ],
            parent: ...
          }
        ],
        parent: ...
      }
    ]
  },
  c3: {
    id: 'c3',
    children: [
      {
        id: 'd1',
        children: [ { id: 'k', children: [], parent: ... } ],
        parent: ...
      }
    ]
  }
}
...