web-dev-qa-db-fra.com

recherche de propriété lodash dans un tableau et dans des tableaux enfant imbriqués

J'ai ce tableau:

[
    {
        id: 1,
        name: 'test 1',
        children: []
    },
    {
        id: 2,
        name: 'test 2',
        children: [
            {
                id: 4,
                name: 'test 4'
            }
        ]
    },
    {
        id: 3,
        name: 'test 3',
        children: []
    }
]

Comment puis-je filtrer par la propriété id dans ce tableau et les tableaux children imbriqués?

Par exemple, la recherche de id = 3, devrait renvoyer le test 3 objet et recherche de id = 4 devrait renvoyer le test 4 objet.

16
Mirza Delic

En utilisant lodash, vous pouvez faire quelque chose comme ceci:

_(data)
    .thru(function(coll) {
        return _.union(coll, _.pluck(coll, 'children'));
    })
    .flatten()
    .find({ id: 4 });

Ici, thru () est utilisé pour initialiser la valeur encapsulée. Il renvoie l'union du tableau d'origine et des enfants imbriqués. Cette structure de tableau est ensuite aplatie à l'aide de flatten () , vous pouvez donc find () l'élément.

31
Adam Boduch

C'est une tâche très simple traversée de l'arbre . La façon la plus simple de le résoudre est la récursivité (lien vers jsbin ). Cela fonctionnera avec n'importe quelle profondeur (avec une limite de récursion bien sûr) et c'est l'un des moyens les plus rapides avec la pire complexité O (n):

function find(id, items) {
  var i = 0, found;

  for (; i < items.length; i++) {
    if (items[i].id === id) {
      return items[i];
    } else if (_.isArray(items[i].children)) {
      found = find(id, items[i].children);
      if (found) {
        return found;
      }
    }
  }
}

Mise à jour:

Pour trouver toutes les correspondances - une fonction légèrement modifiée (le lien jsbin ci-dessus est mis à jour):

function findAll(id, items) {
  var i = 0, found, result = [];

  for (; i < items.length; i++) {
    if (items[i].id === id) {
      result.Push(items[i]);
    } else if (_.isArray(items[i].children)) {
      found = findAll(id, items[i].children);
      if (found.length) {
        result = result.concat(found);
      }
    }
  }

  return result;
}
3
Kiril

Une autre option lodash avec clé enfant et niveaux illimités en profondeur.

const flattenItems = (items, key) => {
    return items.reduce((flattenedItems, item) => {
        flattenedItems.Push(item)
        if (Array.isArray(item[key])) {
            flattenedItems = flattenedItems.concat(flattenItems(item[key], key))
        }
        return flattenedItems
    }, [])
}

const item = find(flattenItems(items, 'children'), ['id', 4])
2
Richard Ayotte