对数组中的项目进行分组和计数的简洁方法
Posted
技术标签:
【中文标题】对数组中的项目进行分组和计数的简洁方法【英文标题】:Concise way to Group by and Count item in array 【发布时间】:2021-06-27 08:04:50 【问题描述】:我有一个这样的数组:
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
来解决。
【问题讨论】:
【参考方案1】:在性能方面,我认为我可以使用简单的for loops as for loops are faster than .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>
【讨论】:
感谢您的回答。但我想到了除_.countBy
之外的另一个lodash's method
。无论如何 +1 尊重。
嗨,我已经更新了我的答案。我认为 'lodash' 中的 _.reduce() 可以用来编写更紧凑和可读的代码。请看一看。
是的,看起来不错。就个人而言,在这种情况下使用Array#reduce
是最简洁的。谢谢。
在性能方面,你觉得Object.entries() + map
和_.countBy(arr, 'country')
之间的_.reduce
之间怎么样?我的意思是 Object.entries
实际上是做什么的?
根据我的观察,Object.entries()
需要一次迭代,然后您使用 map
进行另一次迭代。但是对于`_.reduce()`,您只使用了一次迭代。这取决于 JS 引擎的实现。但大致它会遍历你的对象并返回一个数组。你可以在这里看到developer.mozilla.org/en-US/docs/Web/javascript/Reference/…。【参考方案2】:
万岁!!!
经过最近几天的研究,我终于想出了像这样使用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 result = _(arr).groupBy(x => x.country)
.map((value, key) => (country: key, count: value.length));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
说明:
-
第一步:根据
country
属性对数组元素进行分组
第 2 步:使用具有 2 个参数值的 .map:key
是组的名称(国家/地区),value
是对象数组。
参考资源:
using lodash .groupBy. how to add your own keys for grouped output?【讨论】:
以上是关于对数组中的项目进行分组和计数的简洁方法的主要内容,如果未能解决你的问题,请参考以下文章