首页 > 解决方案 > 对数组中的项目进行分组和计数的简洁方法

问题描述

我有一个这样的数组:

const arr = [ {name: 'Server 1', country: 'DE'}, {name: 'Server 2', country: 'PL'}, 
              {name: 'Server 3', country: 'US'}, {name: 'Server 4', country: 'DE'}, 
              {name: 'Server 5', country: 'US'}];

我想要的是group and count得到如下输出:

 [
  {
    "country": "DE",
    "count": 2
  },
  {
    "country": "PL",
    "count": 1
  },
  {
    "country": "US",
    "count": 2
  }
]

目前,我正在使用lodash,但我认为有更好的方法(例如,使用_groupBy或类似的方法)来解决它,对吧?

我的代码在这里:

const arr = [ {name: 'Server 1', country: 'DE'}, {name: 'Server 2', country: 'PL'}, {name: 'Server 3', country: 'US'}, {name: 'Server 4', country: 'DE'}, {name: 'Server 5', country: 'US'}];

const objectGroupby = _.countBy(arr, 'country');
const result = Object.entries(objectGroupby).map(([key, value]) => ({country: key, count: value}));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

如您所见,_.countBy(arr, 'country')只返回一个对象而不是数组。

{
  "DE": 2,
  "PL": 1,
  "US": 2
}

然后我必须使用Object.entries()&map来解决它。

标签: javascriptgroup-bycountlodash

解决方案


在性能方面,我认为我可以使用简单的 for 循环编写性能更高的代码,因为 for 循环比 .map()、.reduce()等更快。

您可以通过遍历原始数组一次来执行以下操作,

const arr = [ {name: 'Server 1', country: 'DE'}, {name: 'Server 2', country: 'PL'}, {name: 'Server 3', country: 'US'}, {name: 'Server 4', country: 'DE'}, {name: 'Server 5', country: 'US'}];

let mapObj = {};
let res = [];
let resIndex = 0;

for(let i = 0; i < arr.length; i++) {
  if(mapObj[arr[i].country] >= 0) {
    res[mapObj[arr[i].country]].count++;
  } else {
    res.push({country: arr[i].country, count: 1});
    mapObj[arr[i].country] = resIndex;
    resIndex++;
  }
}

console.log(res);

就优雅或更易读的代码而言,我认为使用 reduce 更具可读性。但可读性是主观的,因人而异。对我来说 reduce 会更具可读性。

const arr = [ {name: 'Server 1', country: 'DE'}, {name: 'Server 2', country: 'PL'}, {name: 'Server 3', country: 'US'}, {name: 'Server 4', country: 'DE'}, {name: 'Server 5', country: 'US'}];

res = arr.reduce((prev, curr) => {
  const index = prev.findIndex(item => item.country === curr.country);
  if(index > -1) {
    prev[index].count++;
  } else {
    prev.push({ country: curr.country, count: 1});
  }
  return prev;
}, []);

console.log(res);

更新: 使用 Lodash,

const arr = [ {name: 'Server 1', country: 'DE'}, {name: 'Server 2', country: 'PL'}, {name: 'Server 3', country: 'US'}, {name: 'Server 4', country: 'DE'}, {name: 'Server 5', country: 'US'}];

result = _.reduce(_.countBy(arr, 'country'), (result, value, key) => {
  result.push({ country: key, count: value});
  return result;
}, []);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>


推荐阅读