J'ai une matrice 2D comme celle-ci où la première ligne correspond aux noms des colonnes et les autres lignes sont des valeurs.
var datatable = [ ["a", "b", "d"], //first row are columns names [ 1, 0, 3 ], //other rows are values [ 6, null, 8 ] ];
Je voudrais supprimer des colonnes lorsque toutes les valeurs sont nulles
comme résultat attendu ci-dessous:
var datatable = [ ["a", "b", "c", "d"], //first row are columns names [ 1, 0, null, 3 ], //other rows are values [ 6, null, null, 8 ] ];
Le nombre de lignes et de colonnes peut varier. S'il existe un moyen compact et rapide d'y parvenir avec du lodash, c'est parfait.
4 Réponses :
Vous pouvez d'abord obtenir les colonnes avec toutes les valeurs null
, puis filtrer les lignes.
.as-console-wrapper { max-height: 100% !important; top: 0; }
var datatable = [["a", "b", "c", "d"], [1, 0, null, 3], [6, null, null, 8]], cols = datatable .slice(1) // omit header .reduce((r, a) => a.map((v, i) => r[i] || v !== null), []); datatable = datatable.map(a => a.filter((_, i) => cols[i])); console.log(datatable);
Code légèrement plus long, mais idée similaire.
var datatable = [ ["a", "b", "c", "d"], [1, 0, null, 3], [6, null, null, 8] ]; /* first create a simple key val map as {a:[1,6],b:[0,null] etc to weed out the keys with all nulls */ let keyValMap = datatable.reduce((acc,arr,index) => { if(index===0) { arr.forEach(key => { if(!acc[key]) acc[key]=[] }); } else { Object.keys(acc).map((key,index) => acc[key].push(arr[index])); } return acc; },{}); // now extract only those keys that do not have every element as null let validKeys = Object.keys(keyValMap).filter(key => !keyValMap[key].every(i => i===null)); // pivot back from keyValMap the values based on validKeys let updatedDataTable = [validKeys, ...validKeys.map(key => keyValMap[key]).reduce((acc,val)=>{ val.forEach((elem,i) => { if(!acc[i]) acc[i]=[]; acc[i].push(elem) }); return acc; },[]) ] console.log(updatedDataTable);
Utilisez .flow ()
qui crée une fonction qui transpose le tableau en utilisant _.unzip ()
, rejette les tableaux qui ont tous null
valeurs, puis décompressez le tableau à sa forme d'origine:
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>
const { flow, unzip, reject, tail, every, isNull } = _; // convert to imports const fn = flow( unzip, reject(flow( tail, every(isNull) )), unzip, ); const datatable = [ ["a", "b", "c", "d"], //first row are columns names [ 1, 0, null, 3 ], //other rows are values [ 6, null, null, 8 ] ]; const result = fn(datatable); console.log(result);
Et la solution terser lodash / fp:
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
const { flow, partialRight: pr, unzip, reject, tail, every, isNull } = _; // convert to imports const fn = flow( unzip, pr(reject, flow(tail, pr(every, isNull))), unzip, ); const datatable = [ ["a", "b", "c", "d"], //first row are columns names [ 1, 0, null, 3 ], //other rows are values [ 6, null, null, 8 ] ]; const result = fn(datatable); console.log(result);
Ici vous avez mon approche en utilisant map ()
, filter ()
et some()
.
var datatable = [ ["a", "b", "c", "d"], [ 1, 0, null, 3 ], [ 6, null, null, 8 ] ]; let res = datatable.map( x => x.filter((_, idx) => datatable.slice(1).some(arr => arr[idx] !== null)) ); console.log(res);
car il y avait une valeur dans le deuxième tableau
car toutes les valeurs de la colonne doivent être nulles pour être supprimées
La troisième colonne contient
c
. Pourquoi cela a-t-il été supprimé?car la première ligne correspond aux noms des colonnes et ils ne peuvent jamais être nuls. C'est comme un tableau Excel si vous voulez ...