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 ...