2
votes

mapper un tableau imbriqué en javascript

J'ai un tableau imbriqué d'objets comme celui-ci:

normalizeData(data, arr = []) {
    return data.map((x) => {
        if (Array.isArray(x))
            return this.normalizeData(x, arr)
        return {
            ...x,
            title: x.name,
            children: x.children.length ? [...x.children] : null
        }
    })
}

Tout ce que je veux, c'est trouver récursivement feuilles sans enfants (actuellement un tableau vide) et supprimer la propriété children de leur part.

Voici mon code:

let data = [
  {
      id: 1,
      title: "Abc",
      children: [
          {
              id: 2,
              title: "Type 2",
              children: [
                  {
                      id: 23,
                      title: "Number 3",
                      children:[] /* This key needs to be deleted */
                  }
              ]
          },
      ]
  },
  {
      id: 167,
      title: "Cde",
      children:[] /* This key needs to be deleted */
  }
] 


2 commentaires

Vos efforts jusqu'à maintenant?


code ajouté, veuillez jeter un œil


4 Réponses :


4
votes

Pour cela, vous devez utiliser la récursivité:

let data = [{
    id: 1,
    title: "Abc",
    children: [{
      id: 2,
      title: "Type 2",
      children: [{
        id: 23,
        title: "Number 3",
        children: [] /* This key needs to be deleted */
      }]
    }]
  },
  {
    id: 167,
    title: "Cde",
    children: [] /* This key needs to be deleted */
  }
]

function traverse(obj) {
  for (const k in obj) {
    if (typeof obj[k] == 'object' && obj[k] !== null) {
      if (k === 'children' && !obj[k].length) {
        delete obj[k]
      } else {
        traverse(obj[k])              
      }
    }
  }
}

traverse(data)
console.log(data)


0 commentaires

3
votes

La réponse de Nik est correcte (bien que je ne vois pas l'intérêt d'accéder à la clé children comme ça), mais voici une alternative plus courte si cela peut aider:

data.forEach(deleteEmptyChildren = o => 
  o.children && o.children.length 
    ? o.children.forEach(deleteEmptyChildren) 
    : delete o.children);

Si children n'est pas toujours là, vous pouvez changer la partie principale du code en:

let data = [
  {id: 1, title: "Abc", children: [
    {id: 2, title: "Type 2", children: [
      {id: 23, title: "Number 3", children: []}
    ]}
  ]},
  {id: 167, title: "Cde", children: []}
];

data.forEach(deleteEmptyChildren = o => 
  o.children.length ? o.children.forEach(deleteEmptyChildren) : delete o.children);

console.log(data);


6 commentaires

C'est une très belle solution


Cela échouera s'il n'y a pas de clé enfant dans l'objet


Je ne suis tout simplement pas fan de la boucle supplémentaire pour l'initialiser.


@CodeManiac Eh bien en regardant l'entrée de OP, il semble que c'est toujours là même quand il est vide (c'est pourquoi il veut les supprimer pour commencer). Le code est facilement réglable si ce n'est pas le cas.


@CodeManiac e.children && e.children.length résout le problème donc pas un gros problème


@epascarello J'apprécie un peu plus quand la fonction s'applique à des éléments réels, par opposition à une collection d'éléments, surtout si elle est censée être réutilisée dans des circonstances différentes. Question de préférence, je suppose.



2
votes

Vous pouvez le faire comme ceci en utilisant la récursivité.

Donc ici l'idée de base est dans la fonction removeEmptyChild nous vérifions si la longueur des enfants est non nulle ou non. donc si c'est le cas, nous parcourons chaque élément du tableau des enfants et leur passons à nouveau la fonction en paramètre, si la longueur des enfants est égale à zéro, nous supprimons la clé des enfants.

let data=[{id:1,title:"Abc",children:[{id:2,title:"Type2",children:[{id:23,title:"Number3",children:[]}]},]},{id:167,title:"Cde",children:[]},{id:1}]

function removeEmptyChild(input){
  if( input.children && input.children.length ){
    input.children.forEach(e => removeEmptyChild(e) )
  } else {
    delete input.children
  }
  return input
}

data.forEach(e=> removeEmptyChild(e))

console.log(data)


2 commentaires

pourquoi utilisez-vous map?


@epascarello oh mon mauvais. J'ai négligé l'utilisation de la carte ici. merci d'avoir indiqué le meilleur cas à utiliser pour chaque



2
votes

Une simple récursion avec forEach suffit.

let data = [{
    id: 1,
    title: "Abc",
    children: [{
      id: 2,
      title: "Type 2",
      children: [{
        id: 23,
        title: "Number 3",
        children: [] /* This key needs to be deleted */
      }]
    }, ]
  },
  {
    id: 167,
    title: "Cde",
    children: [] /* This key needs to be deleted */
  }
]

const cleanUp = data =>
  data.forEach(n =>
    n.children.length
      ? cleanUp(n.children)
      : (delete n.children))
      
      
cleanUp(data)
console.log(data)

Cela suppose que les enfants sont là. S'il peut manquer, il faut juste une modification mineure du chèque afin qu'il ne se trompe pas sur le contrôle de longueur. n.children && n.children.length


0 commentaires