从数组的数组中获取计数

7
我有一个数组的数组,如下所示。使用ES6语法,我该如何将每个值GoodExcellentWow的数量统计到一个新数组中,例如[{name: Good, count: 4} {name: Excellent, count: 5}, {name:Wow, count:2}]?我尝试使用Object.assign,但是我无法将关键字计数“唯一化”,相反,我需要使用数组,因为我正在尝试在前端渲染它。我需要使用reduce吗?怎么用?

let k = 0
const stats = {}
const remarks = [
  [{name: "Good"}],
  [{name: "Good"}, {name: "Excellent"}],
  [{name: "Good"}, {name: "Excellent"}, {name: "Wow"}],
  [{name: "Good"}, {name: "Excellent"}, {name: "Wow"}],
  [{name: "Excellent"}],
  [{name: "Excellent"}]
]

remarks.forEach((arr) => {
  arr.map((e) => {
    Object.assign(stats, { [e.name]: k = k + 1 })
  })
})

console.log(stats);

输出:

stats: {Good: 8, Excellent: 11, Wow: 9}

这是不正确的,我需要使用一个数组。

期望的输出:

[{name: Good, count: 4} {name: Excellent, count: 5}, {name:Wow, count:2}]


你为什么要使用类型定义呢?你确定你没有在使用 TypeScript 吗? - Ben
9个回答

6

将数组的嵌套展平,并从对象 { Good: 0, Excellent: 0, Wow: 0} 开始执行reduce操作。

然后用.map对结果中的Object.entries进行转换,以将其转换为一个数组:

const remarks = [
  [{ name: "Good" }],
  [{ name: "Good" }, { name: "Excellent" }],
  [{ name: "Good" }, { name: "Excellent" }, { name: "Wow" }],
  [{ name: "Good" }, { name: "Excellent" }, { name: "Wow" }],
  [{ name: "Excellent" }],
  [{ name: "Excellent" }]
];

const result = Object.entries(
  remarks.flat().reduce(
    (all, { name }) => {
      all[name] += 1;
      return all;
    },
    { Good: 0, Excellent: 0, Wow: 0 }
  )
).map(([name, count]) => ({ name, count }));

console.log(result);


我在使用 flat 时遇到了一个错误:"在类型 '{ name: string; }[][]' 上不存在属性 'flat'。" - colin_dev256
@colin_dev256 用什么浏览器? - Kevin B
2
你只是缺少一个类型定义。 - Kevin B

3
你可以尝试以下逻辑:

var data = [[{name: "Good"}],[{name: "Good"}, {name:"Excellent"}],[{name: "Good"}, {name:"Excellent"}, {name:"Wow"}],[{name: "Good"}, {name:"Excellent"}, {name:"Wow"}],[{name:"Excellent"}],[{name:"Excellent"}]]

var nData = [];

(data || []).forEach( e => {
  (e || []).forEach(ei => {
    var i = (index = nData.findIndex(d => d.name === ei.name)) >=0 ? index : nData.length;
    nData[i] = {
      name: ei.name,
      count : (nData[i] && nData[i].count ? nData[i].count : 0)+1
    }
  });
});

console.log(nData);

希望这能有所帮助!

2
您可以使用reduce,然后将结果转换为对象数组:

最初的回答:您可以使用reduce,然后将结果转换为对象数组:
const counts = remarks.reduce((result, list) => {
  list.forEach(remark => {
    result[remark.name] = (result[remark.name] || 0) + 1;
  });
}, {});
const finalResult = [];
for (let name in counts) {
  finalResult.push({name, count: counts[name]});
}

1

您可以通过以下方式轻松实现:

1)将嵌套数组展开成一个单层数组。

2)遍历该扁平化数组并使用Array.prototype.reduce创建“计数映射”。

例如:

const remarks = [
  [{
    name: 'Good'
  }],
  [{
    name: 'Good'
  }, {
    name: 'Excellent'
  }],
  [{
    name: 'Good'
  }, {
    name: 'Excellent'
  }, {
    name: 'Wow'
  }],
  [{
    name: 'Good'
  }, {
    name: 'Excellent'
  }, {
    name: 'Wow'
  }],
  [{
    name: 'Excellent'
  }],
  [{
    name: 'Excellent'
  }]
]

const flatten = arr => arr.reduce((accum, el) => accum.concat(el), [])
const map = flatten(remarks).reduce((accum, el) => {
  if (accum[el.name]) {
    accum[el.name] += 1;
  } else {
    accum[el.name] = 1;
  }
  return accum;
}, {});

console.log(map)


1
首先使用reduce找到计数,然后将其传递给另一个函数以获得所需的视图结构:

const Good = 1,
      Excellent = 2,
      Wow = 3;

const remarks = [
  [{name: Good}],
  [{name: Good}, {name:Excellent}],
  [{name: Good}, {name:Excellent}, {name:Wow}],
  [{name: Good}, {name:Excellent}, {name:Wow}],
  [{name:Excellent}],
  [{name:Excellent}]
];

/*
[{name: Good, count: 4} {name: Excellent, count: 5}, {name:Wow, count:2}]
*/

function counts(remarks) {
  return remarks.flat().reduce((acc, v) => {
    const name = v.name;
    let count = acc[name] || 0;
    return {
    ...acc,
    [name]: count + 1
    }
  }, {});
}

function view(counts) {
   return Object.keys(counts).map(key => {
     let count = counts[key];
     return { name: key, count };
   })
}

console.log(view(counts(remarks)));


1
任何时候,当你需要处理少量数据或者转换数据时,JavaScript 中的 reduce 方法应该是你尝试使用的第一种方法。在这种情况下,你可能需要将它与索引器配对使用(因此需要预加载一个索引数组和一个结果数组)。
这样做只需要一次遍历,而不需要事先知道名称值。

const remarks = [
  [{name: "Good"}],
  [{name: "Good"}, {name: "Excellent"}],
  [{name: "Good"}, {name: "Excellent"}, {name: "Wow"}],
  [{name: "Good"}, {name: "Excellent"}, {name: "Wow"}],
  [{name: "Excellent"}],
  [{name: "Excellent"}]
];

const stats = remarks.reduce((p,c) => (
  c.forEach( ({name}) => {
    if(!p[0].hasOwnProperty(name)){
      p[1].push({name:name,count:0});
      p[0][name] = p[1].length - 1;
    }
    p[1][p[0][name]].count++;
  }),p),[{},[]])[1];
    
console.log(stats);


1
一个更简洁但肯定不易读的方法(但值得一提)可能是:
const remarks = [
  [{ name: "Good" }],
  [{ name: "Good" }, { name: "Excellent" }],
  [{ name: "Good" }, { name: "Excellent" }, { name: "Wow" }],
  [{ name: "Good" }, { name: "Excellent" }, { name: "Wow" }],
  [{ name: "Excellent" }],
  [{ name: "Excellent" }]
];

const stats = Object.entries(
                remarks
                  .flat()
                  .reduce((acc, {name}) => (acc[name] = -~acc[name], acc), {})))
              ).map(([name, count]) => ({ name, count }));


console.log(stats);

它在reducer中使用逗号运算符返回累加器;并使用按位取反运算符创建一个计数器,无需预先初始化对象中的所有名称。

0
const data = {
    "mchale": {
        "classes":["ESJ030", "SCI339"], // get the length
        "faculty":["Hardy", "Vikrum"]   // get the length
     },
    "lawerence":{
        "classes":["ENG001"],  // get the length
        "faculty":["Speedman", "Lee", "Lazenhower"] // get the length
     }
};

const count = Object.keys(data).map(campusName => {
  const campus = data[campusName];
  return Object.keys(campus).map(key => campus[key].length).reduce((p, c) => p + c, 0);
}).reduce((p, c) => p + c, 0);
console.log(count);

1
如果您在代码中留下一些注释,那就太好了,因为并不总是自我解释为什么您采用了这种解决方案。 - juagicre

0
const flattenedRemarks = _.flatten(remarks);

const groupedRemarks = _.groupBy(flattenedRemarks, (remark) => remark.name);

const remarkCounts = _.mapValues(groupedRemarks, (group) => group.length);

1
谁说 OP 在使用 Underscore? - IceMetalPunk
1
@IceMetalPunk 说他不行? - Kevin B
4
StackOverflow的通常答案政策是即使不必要,也不改变代码的风格;需要新的库则更进一步。至少Robert应该在答案中提到,使用他的解决方案需要Underscore。 - IceMetalPunk
1
那个问题的最佳答案是“几乎从来不需要”。如果“使用jQuery”几乎从来不是一个好答案,为什么“使用Underscore”会更好呢? - IceMetalPunk
1
@IceMetalPunk 这个问题是,“什么情况下使用jQuery 是一个有效的答案。” - Kevin B
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接