2
votes

Convertir un tableau d'objets en objet imbriqué profond en fonction d'une clé spécifique

J'ai un tableau d'objets.

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]})
    }
   })
}

J'ai besoin que l'objet soit organisé dans une hiérarchie. comme ceci,

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

Notez que nous pouvons omettre le tableau dans dernière paire clé (la plus profonde): valeur . C'est ce que j'ai essayé jusqu'à présent.

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

Je pense que ce problème nécessite une programmation dynamique (récursion avec sauvegarde de l'état) dans laquelle je ne suis pas bon. Veuillez aider.


1 commentaires

Je pense que vous avez un objet dont les propriétés sont des tableaux, et non l'inverse. ;-) D'où vient new_hash ?


3 Réponses :


0
votes

Vous pouvez parcourir cette liste parents-enfants sans récursivité pour obtenir l'arborescence.

J'ai omis le code pour transformer les nœuds dans le format que vous décrivez car il est assez tôt le matin pour moi, mais le la transformation devrait être assez simple.

{
  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: ...
      }
    ]
  }
}

rootNodes ressemblera à

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;
});


0 commentaires

1
votes

Vous pourriez prendre une autre table de hachage et y stocker la relation entre tous les nœuds et en retirer pour le résultat uniquement les nœuds qui n'ont pas de parents.

Pour surmonter le problème des nœuds sans enfants, j'ai ajouté un tableau vide, parce que la structure recherchée d'origine a soit null ou aucun enfant du tout, comme ce nœud

.as-console-wrapper { max-height: 100% !important; top: 0; }

où, comme avec un marqueur nul, il devrait être p>

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);

Cette solution comporte un tableau vide, qui peut être remplacé par n'importe quelle autre valeur.

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

{ b1: [{ e: null }] }
{ b1: "e" }


0 commentaires

0
votes

Vous pouvez créer une fonction avec la méthode reduction pour boucler Object.keys et créer une nouvelle structure d'objet et une autre fonction pour vérifier si la clé actuelle est déjà dans l'objet et la renvoyer.

p>

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 commentaires