2 votes

Comment compter et regrouper les valeurs de propriétés multiples dans un tableau d'objets ?

J'ai un tableau d'objets :

[
  {'year': 2019, 'a_academic': 3, 'f_security': 4, ..., 'k_services': 3},
  {'year': 2019, 'a_academic': 2, 'f_security': 2, ..., 'k_services': 4},
  {'year': 2019, 'a_academic': 3, 'f_security': 3, ..., 'k_services': 1},
  ...
  {'year': 2019, 'a_academic': 3, 'f_security': 3, ..., 'k_services': 3},
]

Comment compter les valeurs de plusieurs propriétés, puis les regrouper, et les enregistrer dans un nouvel objet, par exemple :

{
  'a_academic': {
      4: 0,
      3: 3,
      2: 1,
      1: 0
  },
  'f_security': {
      4: 1,
      3: 2,
      2: 1,
      1: 0
  },
  ...,
  'k_services': {
      4: 1,
      3: 2,
      2: 0,
      1: 1
  }
}

Je peux le faire en utilisant reduce et en accédant manuellement à la clé, mais seulement pour une propriété :

let count = array.reduce((res, cur) => {
    res[cur.a_academic] = res[cur.a_academic] ? res[cur.a_academic] + 1 : 1;
    return res;
  }, {});

console.log(count);

Résultat :

{
  3: 3,
  2: 1
}

Comment mettre en œuvre cette méthode de manière efficace pour qu'elle fonctionne pour toutes les autres propriétés, sans y accéder manuellement ?

2voto

Nenad Vracar Points 17412

Vous pourriez définir un tableau de clés que vous voulez compter et ensuite utiliser reduce avec des méthodes imbriquées forEach boucle sur Object.entries et comptez les valeurs qui apparaissent pour chacune de ces clés définies.

const data = [
  {'year': 2019, 'a_academic': 3, 'f_security': 4, 'k_services': 3},
  {'year': 2019, 'a_academic': 2, 'f_security': 2, 'k_services': 4},
  {'year': 2019, 'a_academic': 3, 'f_security': 3, 'k_services': 1},
  {'year': 2019, 'a_academic': 3, 'f_security': 3, 'k_services': 3},
]

const props = ['a_academic', 'f_security', 'k_services']

const result = data.reduce((r, e) => {
  Object.entries(e).forEach(([k, v]) => {
    if (props.includes(k)) {
      if (!r[k]) r[k] = {}
      r[k][v] = (r[k][v] || 0) + 1
    }
  })
  return r;
}, {})

console.log(result)

Pour remplir les valeurs vides dans chaque objet, il faudrait d'abord trouver les valeurs min et max pour l'ensemble des données, mais aussi pour les seuls accessoires définis.

const data = [
  {'year': 2019, 'a_academic': 3, 'f_security': 4, 'k_services': 3},
  {'year': 2019, 'a_academic': 2, 'f_security': 2, 'k_services': 4},
  {'year': 2019, 'a_academic': 3, 'f_security': 3, 'k_services': 1},
  {'year': 2019, 'a_academic': 3, 'f_security': 3, 'k_services': 3},
]

const props = ['a_academic', 'f_security', 'k_services']

const values = data.map(e => {
  return Object.entries(e)
    .filter(([k]) => props.includes(k))
    .map(([k, v]) => v)
}).flat()

const max = Math.max(...values)
const min = Math.min(...values)

const result = data.reduce((r, e) => {
  Object.entries(e).forEach(([k, v]) => {
    if (props.includes(k)) {
      if (!r[k]) {
        r[k] = {}

        for (let i = min; i <= max; i++) {
          r[k][i] = 0
        }
      }

      r[k][v] += 1
    }
  })
  return r;
}, {})

console.log(result)

1voto

Nina Scholz Points 17120

Vous avez besoin d'un regroupement imbriqué en omettant year des objets.

var data = [{ year: 2019, a_academic: 3, f_security: 4, k_services: 3 }, { year: 2019, a_academic: 2, f_security: 2, k_services: 4 }, { year: 2019, a_academic: 3, f_security: 3, k_services: 1 }, { year: 2019, a_academic: 3, f_security: 3, k_services: 3 }],
    grouped = data.reduce((r, { year, ...o }) => {
        Object.entries(o).forEach(([k, v]) => {
            r[k] = r[k] || {};
            r[k][v] = (r[k][v] || 0) + 1;
        });
        return r;
    }, {});

console.log(grouped);

0voto

cr05s19xx Points 128

Ce que vous avez fait, c'est d'utiliser le valeur de cur.academic au lieu du nom de la clé. Pour mieux expliquer cela, considérez ceci

const obj = { alpha: 20, beta: 30, gamma: 40 };

console.log(obj['alpha']); // outputs 20

Ce que vous pouvez faire, c'est ça :

const array = [
  {'year': 2019, 'a_academic': 3, 'f_security': 4, 'k_services': 3},
  {'year': 2019, 'a_academic': 2, 'f_security': 2, 'k_services': 4},
  {'year': 2019, 'a_academic': 3, 'f_security': 3, 'k_services': 1},
  {'year': 2019, 'a_academic': 3, 'f_security': 3, 'k_services': 3},
];

const excludedKeys = ['year'];
let count = array.reduce((res, curr) => {
    // Select the keys you are going to use and exclude the ones you won't
    const keys = Object.keys(curr).filter(key => !excludedKeys.includes(key));

    keys.forEach(key => {
        res[key] = res[key] ? res[key] + 1 : 1;
    });

    return res;
}, {});

console.log(count);

0voto

Nick Parsons Points 2103

Vous pouvez saisir les clés d'un de vos objets (à l'exception de year ), puis de faire correspondre chaque clé à un tableau de points. Par exemple, a_academic a le tableau de valeurs de [3, 2, 3, 3] qui est mis en correspondance avec [0, 0, 1, 3, 0] . En utilisant ce total vous pouvez utiliser Object.assign() pour affecter ses index à un objet, que vous pouvez utiliser pour chaque groupe comme suit :

const arr = [
  {'year': 2019, 'a_academic': 3, 'f_security': 4, 'k_services': 3},
  {'year': 2019, 'a_academic': 2, 'f_security': 2, 'k_services': 4},
  {'year': 2019, 'a_academic': 3, 'f_security': 3, 'k_services': 1},
  {'year': 2019, 'a_academic': 3, 'f_security': 3, 'k_services': 3},
];

const groupArr = ([{year, ...first}, ...arr]) => {
  const ent = Object.entries(first);
  const gr = ent.map(([key, v]) => [v, ...arr.map(o => o[key])]);
  const maxN = Math.max(...gr.flat());
  const minN = Math.min(...gr.flat());

  const total = gr.map(arr =>
    arr.reduce((tally, n) => (tally[n]++, tally), Array(minN).concat(Array(maxN).fill(0)))
  );
  return Object.assign({}, ...ent.map(([k], i) => ({[k]: Object.assign({}, total[i])})));
}

console.log(groupArr(arr));

0voto

Siva K V Points 7557

Il suffit d'ajouter Object.keys pour que votre logique accède aux clés de façon dynamique.

const array = [
  { year: 2019, a_academic: 3, f_security: 4, k_services: 3 },
  { year: 2019, a_academic: 2, f_security: 2, k_services: 4 },
  { year: 2019, a_academic: 3, f_security: 3, k_services: 1 },
  { year: 2019, a_academic: 3, f_security: 3, k_services: 3 }
];

let count = array.reduce((res, cur) => {
  Object.keys(cur)
    .filter(key => key.includes("_"))
    .forEach(key => {
      const obj = res[key] || {};
      res[key] = {
        ...obj,
        [cur[key]]: (obj[cur[key]] || 0) + 1
      };
    });
  return res;
}, {});

console.log(count);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X