2
votes

Aplatir un tableau avec des objets imbriqués

J'ai un tableau avec des objets, qui peuvent avoir des enfants, les enfants ont la même structure que le parent, c'est juste une imbrication d'objets en gros.

Je me demande comment je peux aplatir la structure de mes objets donc j'ai les identifiants de tous les objets, y compris celui imbriqué.

Par exemple, Cette structure

const data = [2,1,3]

Doit être aplatie à ceci

const data = [
  {
    id: 2,
    children: [
      {
        id: 1,
        children: []
      }
    ]
  },
  {
    id: 3,
    children: [],
  }
]

J'ai essayé

En utilisant Array.reduce () et la syntaxe de propagation d'objets, mais je ne peux pas comprendre la logique nécessaire pour ce faire.


0 commentaires

9 Réponses :


1
votes

Vous pouvez utiliser JSON.stringify , et pour chaque clé de id , pousser vers un tableau:

const data = [
  {
    id: 2,
    children: [
      {
        id: 1,
        children: []
      }
    ]
  },
  {
    id: 3,
    children: [],
  }
]
const ids = [];
JSON.stringify(data, (key, val) => {
  if (key === 'id') {
    ids.push(val);
  }
  return val;
});
console.log(ids);


2 commentaires

Ohhh - Cool. Je n'avais aucune idée que stringify prenait des paramètres. J'ai aussi utilisé stringify puis une regex


Curieusement, cela ne se répète pas: JSON.stringify (data, ["id"])



3
votes

C'est un travail de récursivité. Faites une boucle sur le tableau et pour chaque élément qu'il contient, insérez l'identifiant dans un nouveau tableau et répétez pour les enfants.

const data = [{
    id: 2,
    children: [{
      id: 1,
      children: []
    }]
  },
  {
    id: 3,
    children: [],
  }
];

console.log(flatten(data));

function flatten(data) {
  const result = [];
  recursive(data);
  return result;

  function recursive(data) {
    data.forEach(member => {
      result.push(member.id);
      recursive(member.children);
    });
  }
}


0 commentaires

1
votes

Vous pouvez utiliser une approche récursive.

const data = [{
    id: 2,
    children: [{
      id: 1,
      children: []
    }]
  },
  {
    id: 3,
    children: [],
  }
];

function flatArr(arr, res) {
  // iterate over the array
  arr.forEach(o => {
    // check id is present then push it into the result array
    if ('id' in o) res.push(o.id)
    // check children is present and non-empty
    // then ecursively call the function
    if (o.children && o.children.length) flatArr(o.children, res);
  })
  // return the result array(optional since it's the same array reference you are passing initially)
  return res;
}

console.log(flatArr(data, []));

function flatArr(arr, res) {
  // iterate over the array
  arr.forEach(o => {
    // check id is present then push it into the result array
    if ('id' in o) res.push(o.id)
    // check children is present and non-empty
    // then ecursively call the function
    if (o.children && o.children.length) flatArr(o.children, res);
  })
  // return the result array(optional)
  return res;
}

console.log(flatArr(data, []));


0 commentaires

0
votes

Vous pouvez réduire le tableau des objets en utilisant l'ID réel et obtenir leurs objets enfants.

const
    getId = array => array.reduce(
        (r, { id, children }) => [...r, id, ...getId(children)],
        []
    ),
    data = [{ id: 2, children: [{ id: 1, children: [] }] }, { id: 3, children: [] }],
    ids = getId(data);
    
console.log(ids);


0 commentaires

0
votes

Vous pouvez utiliser une approche récursive et itérer pour chaque enfants et pousser tous les id dans un tableau.

const data = [{ id: 2, children: [{ id: 1, children: [] }] }, { id: 3, children: [], } ],
      getId = (data) => data.reduce((r,{id, children}) => r.concat(id, getId(children)),[]);
console.log(getId(data));


0 commentaires

3
votes

const data = [
  {
    id: 2,
    children: [
      {
        id: 1,
        children: []
      }
    ]
  },
  {
    id: 3,
    children: [],
  }
]

const getIds = (data) => data.map(d => [d.id, ...getIds(d.children)]).flat()

console.log(getIds(data))


2 commentaires

C'est élégant


J'ai accepté cette réponse, comme la ligne! Merci



1
votes

Vous pouvez utiliser la récursivité.Notez que ci-dessous la référence de code de arr est passée afin que nous puissions directement pousser () les identifiants dessus et pas besoin d'obtenir renvoie valeur

const data = [{ id: 2, children: [{ id: 1, children: [] }] }, { id: 3, children: [], } ]

function getIds(data,arr){
  //iterate over array of chilren
  for(let child of data){
    //add id of each child to arr
    arr.push(child.id);
    //check if child have children add its 'ids' to same array
    if(child.children) getIds(child.children,arr);
  }
  //return array in end
  return arr;
}
console.log(getIds(data,[]))


0 commentaires

1
votes

Je n'aime pas les récursions :)

Notez l'autre réponse Stringify - ILST
https://stackoverflow.com/a/55179326/295783

const data=[{id:2,children:[{id:1,children:[]}]},{id:3,children:[],}];

console.log(
  JSON.stringify(data)
    .match(/(?:"id":)(\d+)/g)
    .map(v => +v.replace(/"id":/g, ""))
)

Je souhaite cependant que quelqu'un puisse me trouver un moyen d'ignorer le groupe non capturant en une seule fois


2 commentaires

Convertissez chaque valeur en Number . Solution vraiment étrange +1


@MaheerAli Terminé;)



0
votes

Une autre version. Pas le plus joli mais fait le travail:

const data = [
    {
        id: 2,
        children: [
            {
                id: 1,
                children: []
            }
        ]
    },
    {
        id: 3,
        children: [],
    }
];
    
let mappedArray = data.map(num => [].concat(num.children.map(child => child.id)).concat(num.id));
    mappedArray = [].concat.apply([], mappedArray);

console.log(mappedArray);


0 commentaires