3
votes

Comment utiliser Array.prototype.map () sur un tableau d'objets pour filtrer certaines clés spécifiques en fonction de ses valeurs?

J'ai le tableau d'objets suivant, dans lequel certaines clés spécifiques ont une valeur qui est soit une chaîne, soit un tableau. Je veux obtenir les clés avec des valeurs de chaîne telles quelles et supprimer "NA" des clés avec des valeurs de tableau.

J'essaie d'obtenir la même chose en faisant la méthode .map sur le tableau, vérifiez le type de la valeur de chaque entrez l'objet de données, si un tableau utilise alors .filter pour supprimer les valeurs "NA".

var dataArr = [
    {
     a: 'foo',
     b: [1, 2, "NA", "NA", 3],
     c: ["NA", 6]
    },
    {
     a: 'bar',
     b: ["NA", "NA", "NA"],
     c: []
    }
];
dataArr.map(dataObj => {
    for (let key in dataObj) {
        if (key !== 'a')
            dataObj[key] = dataObj[key].filter(val => { if(val != "NA") return val})
    }
    return dataObj;
});

Le bloc de code ci-dessus fonctionne comme prévu mais je veux un meilleur et solution pérenne. De plus, cela semble mauvais aussi.


4 commentaires

Votre code actuel mute le dataArr d'origine, est-ce vraiment souhaitable?


dataArr [0] .map ne fonctionnera pas. Vous utilisez map sur JS Object. Les objets n'ont pas de fonction de carte.


@Shubham merci d'avoir souligné, c'est une faute de frappe. Je suis en train de modifier la question.


@CertainPerformance Oui, je suis conscient du problème de la mutation, merci de l'avoir signalé. Mais la mutation n'aura aucun impact ici puisque je nettoie les valeurs indésirables.


5 Réponses :


1
votes

Utilisez for ... of sur les entrées de l'objet. Pour chaque entrée, vérifiez s'il s'agit d'un tableau. S'il s'agit d'un filtre de tableau, puis affectez-le au nouvel objet. Sinon, attribuez sans filtrage. Cela ne modifiera pas le tableau d'origine.

const dataArr = [{"a":"foo","b":[1,2,"NA","NA",3],"c":["NA",6]},{"a":"bar","b":["NA","NA","NA"],"c":[]}]

const result = dataArr.map(dataObj => {
  const filterObject = {};
  
  for (const [key, val] of Object.entries(dataObj)) {
    filterObject[key] = Array.isArray(val) ?
      dataObj[key].filter(val => val != 'NA')
      :
      val;
  }
  
  return filterObject;
});

console.log(result);


0 commentaires

2
votes

Vous pouvez le faire en utilisant map () et filter()

    imbriqués
  • Tout d'abord, utilisez map () sur le tableau principal.
  • Récupérez ensuite les entrées de chaque objet en utilisant Object.entries()
  • Utilisez ensuite map () sur les entrées de chaque objet.
  • Renvoie la valeur telle quelle si le Array.isArray est false sinon renvoie la valeur filtrée du tableau.
  • Enfin, utilisez Object.fromEntries () pour créer un objet.

var dataArr = [
    {
     a: 'foo',
     b: [1, 2, "NA", "NA", 3],
     c: ["NA", 6]
    },
    {
     a: 'bar',
     b: ["NA", "NA", "NA"],
     c: []
    }
];

const res = dataArr.map(x => 
               Object.fromEntries(
                   Object.entries(x)
                     .map(([k,v]) => 
                        [k,Array.isArray(v) ? v.filter(b => b !== "NA") : v])
                     )
               )

console.log(res)


3 commentaires

Merci d'avoir répondu, mais je ne pense pas que cela résout le problème de la complexité du temps.


@SibasishMohanty Vous n'avez rien mentionné concernant la complexité du temps dans la question. Quel est le problème de la complexité du temps?


Je me demandais simplement si je pouvais obtenir une meilleure complexité temporelle puisque le nombre de clés est de l'ordre de milliers pour chaque objet.



2
votes

Si vous souhaitez simplement mettre à jour le tableau d'origine, vous pouvez parcourir le tableau en utilisant forEach . Puis parcourez les clés de chaque objet en utilisant pour ... dans et vérifiez s'il s'agit d'un tableau en utilisant Array.isArray () . Mettez à jour la propriété après filtrage la valeur NA

const dataArr = [{a:'foo',b:[1,2,"NA","NA",3],c:["NA",6]},{a:'bar',b:["NA","NA","NA"],c:[]}];

const newArray = dataArr.map(o => {
  const newObj = {};
  
  for (const key in o) {
    if (Array.isArray(o[key]))
      newObj[key] = o[key].filter(s => s !== "NA")
    else
      newObj[key] = o[key]
  }
  
  return newObj;
})

console.log(newArray)

Si vous voulez obtenir un nouveau tableau sans muter les objets d'origine, vous pouvez utiliser map comme ceci:

const dataArr = [{a:'foo',b:[1,2,"NA","NA",3],c:["NA",6]},{a:'bar',b:["NA","NA","NA"],c:[]}];

dataArr.forEach(o => {
  for (const key in o) {
    if (Array.isArray(o[key]))
      o[key] = o[key].filter(s => s !== "NA")
  }
})

console.log(dataArr)


0 commentaires

0
votes

    const dataArr = [{
            a: 'foo',
            b: [1, 2, "NA", "NA", 3],
            c: ["NA", 6]
        },
        {
            a: 'bar',
            b: ["NA", "NA", "NA"],
            c: []
        }
    ];

    const res = dataArr.map((obj) => {
        for(let i in obj){
            if(Array.isArray(obj[i])){
                obj[i] = obj[i].filter(el=>el!=="NA")
            }
        }
        return obj;
    });

    console.log('@>res', res)


1 commentaires

Merci pour la réponse, mais le nombre de clés dans mon objet est trop grand pour vérifier toutes leurs valeurs individuellement.



0
votes

Je suppose que ce sera un meilleur refactor de code, les pls fournissent également la sortie souhaitée:

dataArr.forEach(object=>{
  for (let value in object){
   let isArr = Object.prototype.toString.call(data) == '[object Array]';
   isArr? object[value] = object[value].filter(val => {return val != "NA"}):null}
 })


2 commentaires

Le tableau typeof est également un "objet" .


J'ai modifié la solution, veuillez la vérifier, référencée à partir de stackoverflow.com/questions/12996871/...