web-dev-qa-db-fra.com

Lodash - Trouver en profondeur dans un tableau d'objets

J'ai un tableau d'un objet comme celui-ci

[
    {
        'a': 10,
        elements: [
            {
                'prop': 'foo',
                'val': 10
            },
            {
                'prop': 'bar',
                'val': 25
            },
            {
                'prop': 'test',
                'val': 51
            }
        ]
    },
    {
        'b': 50,
        elements: [
            {
                'prop': 'foo',
                'val': 30
            },
            {
                'prop': 'bar',
                'val': 15
            },
            {
                'prop': 'test',
                'val': 60
            }
        ]
    },
]

Ce dont j'ai besoin, c'est d'additionner la propriété Val lorsque prop est foo. Je dois donc effectuer une recherche parmi les éléments et obtenir tous les objets où prop est foo. Avec cet objet, je devrais résumer la propriété val.

J'ai essayé d'utiliser plusieurs combinaisons de _.find, _.pick et ainsi de suite, mais je n'obtiens pas le bon résultat. Est-ce que quelqu'un peut m'aider?

7
Mistre83

Voici une solution qui flatte les éléments puis filtres le résultat pour obtenir les éléments requis avant sommant la propriété val:

var result = _.chain(data)
    .map('elements')               // pluck all elements from data
    .flatten()                     // flatten the elements into a single array
    .filter({prop: 'foo'})         // exatract elements with a prop of 'foo'
    .sumBy('val')                  // sum all the val properties
    .value()

Le chaînage est un moyen d'appliquer une séquence d'opérations à certaines données avant de renvoyer une valeur. L'exemple ci-dessus utilise un chaînage explicite, mais pourrait être écrit (peut-être devrait l'être) à l'aide d'un chaînage implicite:

var result = _(data)
    .map('elements')
    .flatten()
    .filter({prop: 'foo'})
    .sumBy('val');
12
Gruff Bunny

J'ai créé une bibliothèque que vous pouvez utiliser: https://github.com/dominik791/obj-traverse

La méthode findAll() devrait résoudre votre problème. Le premier paramètre est un objet racine, pas un tableau, vous devriez donc le créer en premier:

var rootObj = {
  name: 'rootObject',
  elements: [
    {
      'a': 10,
       elements: [ ... ]
    },
    {
       'b': 50,
       elements: [ ... ]
    }
  ]
};

Ensuite, utilisez la méthode findAll():

var matchingObjects = findAll( rootObj, 'elements', { 'prop': 'foo' } );

La variable matchingObjects stocke tous les objets avec prop égal à foo. Et à la fin, calculez votre somme:

var sum = 0;
matchingObjects.forEach(function(obj) {
  sum += obj.val;
});
4
dominik791

Vous pouvez parcourir les données et obtenir la somme. Essayez ceci:

var arr=[
     {
         'a': 10,
         elements: [
             {
                 'prop': 'foo',
                 'val': 10
             },
             {
                 'prop': 'bar',
                 'val': 25
             },
             {
                 'prop': 'test',
                 'val': 51
             }
         ]
     },
     {
         'b': 50,
         elements: [
             {
                 'prop': 'foo',
                 'val': 30
             },
             {
                 'prop': 'bar',
                 'val': 15
             },
             {
                 'prop': 'test',
                 'val': 60
             }
         ]
     }
 ];
 var sum=0;
 for(x in arr){
 for(i in arr[x]['elements']){
   if(arr[x]['elements'][i]['prop'] == 'foo'){
	   sum=sum+arr[x]['elements'][i]['val'];
   }
 }

 }

 console.log(sum);

UTILISER LE FILTRE:

var arr=[
     {
         'a': 10,
         elements: [
             {
                 'prop': 'foo',
                 'val': 10
             },
             {
                 'prop': 'bar',
                 'val': 25
             },
             {
                 'prop': 'test',
                 'val': 51
             }
         ]
     },
     {
         'b': 50,
         elements: [
             {
                 'prop': 'foo',
                 'val': 30
             },
             {
                 'prop': 'bar',
                 'val': 15
             },
             {
                 'prop': 'test',
                 'val': 60
             }
         ]
     }
 ];
 var sum=0;

arr.filter(function (person) { 
  person['elements'].filter(function(data){
  if (data.prop == "foo"){
    sum=sum+data.val;
  }
  });
  });
           
           console.log(sum);

0
Suchit kumar

Vous pouvez utiliser _.eachDeep method de deepdash:

var sum = 0;
_.eachDeep(obj,
  function(value, key, path, depth, parent) => {
    sum += (key == 'prop' && value == 'foo' && parent.val) || 0;
  }
);

voici un exemple pour votre cas

0
Yuri Gor