1
votes

Itérer à travers un objet imbriqué et obtenir obj par valeur en utilisant es6 +

Pour un objet de cette structure:

  findObj(obj, id) {
    if (obj.id === id) {
      return obj;
    }

    obj.forEach(x => {
      if (x.id === id) {
        return x;
      } else {
        this.findObj(x.children, id);
      }
    });
  }

Comment obtenir un objet par valeur (id)? Donc je cherche une fonction où si j'appelle ceci:

    {
      id: 3,
      name: '3',
      children: []
    }

Cela renverrait ceci:

findObj(myObj, 3);

Un autre exemple:

       {
          id: 6,
          name: '6',
          children: [
            {
              id: 7,
              name: '7',
              children: []
            }
          ]
        }

Renvoyer ceci:

findObj(myObj, 6);

Je sais que j'ai besoin d'une fonction de récursivité. Voici ce que j'ai jusqu'à présent:

const myObj = {
  id: 1,
  name: '1',
  children: [
    {
      id: 2,
      name: '2',
      children: [
        {
          id: 3,
          name: '3',
          children: []
        }
      ]
    },
    {
      id: 4,
      name: '4',
      children: [
        {
          id: 5,
          name: '5',
          children: [
            {
              id: 6,
              name: '6',
              children: [
                {
                  id: 7,
                  name: '7',
                  children: []
                }
              ]
            }
          ]
        }
      ]
    },
  ]
}

(Ceci est dans une classe angulaire)


4 commentaires

la recherche du parent est trompeuse, car vous recherchez l'élément lui-même. btw, qu'avez-vous essayé?


ouais ive a édité ma réponse juste maintenant haha ​​@NinaScholz


Considérez ce que cela signifie dans la fonction parent si vous retournez depuis une fonction de rappel. Considérez ensuite ce que fait Array # forEach .


J'implémente une solution générique deepFind dans ce Q&R . Je pense que vous le trouverez utile: D


3 Réponses :


1
votes

Deux problèmes:

  • votre instruction return x; retourne uniquement à partir du rappel forEach , pas de la fonction findObj . N'utilisez pas forEach ! Une simple boucle for… of fera l'affaire
  • si votre appel récursif trouve l'objet et le renvoie, vous l'ignorez et continuez simplement à itérer. Vérifiez si vous avez obtenu un résultat et gérez-le correctement.

Je suppose que vous ne cherchez pas une solution complète, alors je laisse cela comme un exercice :-)


0 commentaires

1
votes

Vous pouvez vérifier l'objet ou vérifier les enfants.

.as-console-wrapper { max-height: 100% !important; top: 0; }
function find(object, id) {
    var result;
    if (object.id === id) return object;
    object.children.some(o => result = find(o, id));
    return result;
}

const object = { id: 1, name: '1', children: [{ id: 2, name: '2', children: [{ id: 3, name: '3', children: [] }] }, { id: 4, name: '4', children: [{ id: 5, name: '5', children: [{ id: 6, name: '6', children: [{ id: 7, name: '7', children: [] }] }] }] }] };

console.log(find(object, 5));
console.log(find(object, 6));


0 commentaires

4
votes

À première vue, je vois quelques problèmes.

Si vous avez déjà le ob.id === id dans la fonction, vous n'avez pas besoin de le vérifier plus tard. De plus, si findObj est une fonction définie dans la portée comme n'importe quelle autre variable et n'est pas dans la définition "class", vous n'avez pas besoin de l'appeler via this , de la même manière que le premier appel à findObj vous le faites sans le mot-clé this .

De plus, au début, vous passez un objet à votre méthode, mais ensuite vous passez un tableau d'objets (le obj.children ), et vous vérifiez également l'id dans une méthode forEach , où vous passez une fonction (le x => {... thingy), donc quand vous revenez, vous revenez de cette fonction au lieu de la fonction principale.

Je l'ai corrigé pour vous. Je vous recommande de comprendre ce qui se passe et d'en tirer des leçons, car cela ne se produira pas si vous savez ce que vous faites (le débogage est votre maître ici).

findObj(obj, id) {
    if (obj.id === id) {
        return obj;
    }
    for (var i = 0; i < obj.children.length; i++) { // No forEach, so when we return, we actually return from findObj
        var r = findObj(obj.children[i], id); // We see if we have any return and let the "check logic" be defined on one location instead of duplicated.
        if (r) {
            return r;
        }
    }
}


1 commentaires

Il existe également de bonnes alternatives, comme décrit dans le Documentation forEach MDN : Il n'y a aucun moyen d'arrêter ou de rompre une boucle forEach () autrement qu'en lançant une exception. Si vous avez besoin d'un tel comportement, la méthode forEach () n'est pas le bon outil.