1
votes

lodash - Supprime les colonnes de la table de données (matrice 2D) si toutes les valeurs sont nulles

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 commentaires

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


4 Réponses :


3
votes

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);


0 commentaires

1
votes

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);


0 commentaires

3
votes

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);


0 commentaires

2
votes

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);


0 commentaires