繁体   English   中英

如何对对象数组中的多个属性值进行计数和分组?

[英]How to count and group multiple properties values in array of objects?

我有一个对象数组:

[
  {'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},
]

如何计算多个属性值,然后将其分组,并将其保存在一个新对象中,例如:

{
  '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
  }
}

我可以使用 reduce 和手动访问密钥来做到这一点,但仅限于一个属性:

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

结果:

{
  3: 3,
  2: 1
}

如何有效地实现这一点,使其适用于所有其他属性,而无需手动访问它?

您可以定义一个要计算的键数组,然后在Object.entries上使用带有嵌套forEach循环的reduce方法,并计算每个已定义键的出现值。

 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)

要在每个对象中填充空值,您必须首先找到整个数据的最小值和最大值,而且还必须仅找到定义的道具。

 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)

您需要通过从对象中省略year来进行嵌套分组。

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

你所做的是使用cur.academic而不是键名。 为了更好地解释这一点,请考虑这个

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

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

你可以做的是:

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

您可以从一个对象(不包括year )中获取键,然后将每个键映射到一个计数数组。 例如, a_academic的值数组[3, 2, 3, 3]映射到[0, 0, 1, 3, 0] 使用这个total组,您可以使用Object.assign()将其索引分配给一个对象,您可以将其用于每个组,如下所示:

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

只需为您的逻辑添加Object.keys循环即可动态访问密钥。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM