web-dev-qa-db-fra.com

Filtrage d'un tableau d'objets avec des tableaux en fonction de la valeur imbriquée

J'essaie de filtrer un tableau, en fonction d'un objet imbriqué. J'en ai préparé Fiddle

Le tableau d'entrée ressemble à ceci:

let arrayOfElements = 
    [
        {
           "name": "a",
           "subElements": 
           [
             {"surname": 1},
             {"surname": 2}
           ]
        },
        {
           "name": "b",
           "subElements": 
           [
             {"surname": 3},
             {"surname": 1}
           ]
        },
        {
           "name": "c",
           "subElements": 
           [
             {"surname": 2},
             {"surname": 5}
           ]
        }
    ];

Je veux que la sortie de ce cas ressemble à ceci:

let filteredArray = 
    [
        {
          "name": "a",
          "subElements": 
          [
            {"surname": 1}
          ]
        },
        {
          "name": "b",
          "subElements": 
          [
            {"surname": 1}
          ]
        }
];

J'utilise cette formule pour ce faire:

let filteredArray = arrayOfElements.filter((element) => element.subElements.some((subElement) => subElement.surname === 1));

La sortie est presque bonne, mais elle renvoie des objets avec tous les objets avec des noms de famille (mieux vaut vérifier ce violon: D), au lieu de les couper. Comment puis-je améliorer le filtrage?

14
bartosz.baczek

Après avoir appelé filter, vous devez diriger les résultats vers map, comme ceci:

let filteredArray = arrayOfElements
  .filter((element) => 
    element.subElements.some((subElement) => subElement.surname === 1))
  .map(element => {
    let newElt = Object.assign({}, element); // copies element
    return newElt.subElements.filter(subElement => subElement.surname === '1');
  });

Je suppose ici que vous ne voulez pas manipuler le tableau d'origine. Donc, j'utilise Object.assign.

22
Andrew Eisenberg
let filteredArray = arrayOfElements
  .filter((element) => 
    element.subElements.some((subElement) => subElement.surname == 1))
  .map(element => {
    return Object.assign({}, element, {subElements : element.subElements.filter(subElement => subElement.surname == 1)});

  }); 
10
Mohak Londhe

De cette façon, vous pouvez aller aussi loin que vous le souhaitez dans un tableau et filtrer les éléments à n'importe quel niveau,

arrayOfElements.map((element) => {
  return {...element, subElements: element.subElements.filter((subElement) => subElement.surname === 1)}
})

Spread operator développera element puis remplacera la clé subElements par des valeurs filtrées.

5
Nitesh Ranjan

Essayez cette solution:

data_filter = arrayOfElements.filter(function (element) {
    return element.subElements.some( function (subElement) {
        return subElement.surname === surname
    });
});
4
Praveenkarthi

Amélioration des réponses ci-dessus

let elements = 
    [
        {
           "name": "a",
           "subElements": 
           [
             {"surname": 1},
             {"surname": 2}
           ]
        },
        {
           "name": "b",
           "subElements": 
           [
             {"surname": 3},
             {"surname": 1}
           ]
        },
        {
           "name": "c",
           "subElements": 
           [
             {"surname": 2},
             {"surname": 5}
           ]
        }
    ];
var value = 1;

var filteredArray = elements
.filter(element => element.subElements
  .some(subElement => subElement.surname === value)
)
.map(element => {
  let n = Object.assign({}, element, {'subElements': element.subElements.filter(
    subElement => subElement.surname === value
  )})
  return n;
})

console.log(filteredArray)
4
Sarvar Nishonboev

Vous pouvez également le rendre générique:

Logique

  • Trouver tous les noms de famille distincts et les parcourir
  • Filtrez chaque objet pour vérifier s'il existe des noms de famille. Si oui, copiez l'objet en utilisant Object.assign et définissez la valeur subElements sur la liste filtrée.
  • Créez un tableau temporaire pour contenir tous les objets similaires et appuyez sur l'objet copié.
  • Poussez ce tableau vers le tableau final à chaque itération de nom de famille distinct.

Échantillon

let arrayOfElements=[{name:"a",subElements:[{surname:1},{surname:2}]},{name:"b",subElements:[{surname:3},{surname:1}]},{name:"c",subElements:[{surname:2},{surname:5}]}];
 let distinct_surnames = [];
 arrayOfElements.forEach(function(el) {
   el.subElements.forEach(function(s) {
     if (distinct_surnames.indexOf(s.surname) < 0) distinct_surnames.Push(s.surname)
   });
 })

 let result = [];
 distinct_surnames.forEach(function(sn) {
   let inter = [];
   arrayOfElements.forEach(function(el) {
     let f = el.subElements.filter(function(sub) {
       return sub.surname === sn;
     });
     if (f.length > 0) {
       let _tmp = Object.assign({}, el);
       _tmp.subElements = f;
       inter.Push(_tmp);
     }
   });
   result.Push(inter);
 })
 console.log(result)

Remarque: Les fonctions fléchées sont utilisées pour conserver la référence de this. Si vous n'utilisez pas this à l'intérieur de la fonction, vous pouvez également utiliser des fonctions normales.

1
Rajesh
let filteredArray = arrayOfElements
    .filter((element) => 
        element.subElements.some((subElement) => subElement.surname === 1))
    .map(element => {
        let newElt = Object.assign({}, element); // copies element
        newElt.subElements = newElt.subElements.filter(subElement => subElement.surName === '1'); 
        return newElt;
    });

est plus correctement

1
Ilya Alexeev
function display_message() {
  let arrayOfElements = [{
    "name": "a",
    "subElements": [{
      "surname": 1
    }, {
      "surname": 2
    }]
  }, {
    "name": "b",
    "subElements": [{
      "surname": 3
    }, {
      "surname": 1
    }]
  }, {
    "name": "c",
    "subElements": [{
      "surname": 2
    }, {
      "surname": 5
    }]
  }];
  // console.log(arrayOfElements);
var surname = 1;
  let filteredArray = arrayOfElements.filter((element) => element.subElements.some((subElement) => subElement.surname === surname));

  for(var data in filteredArray){
    filteredArray[data].subElements = {"surname": surname};
    }
  console.log(filteredArray);

}
<input type="button" onclick="display_message();" value="click"/>
1
Himanshu Tyagi