在Javascript中,我试图采取数字值的初始数组,并计算其中的元素。理想情况下,结果将是两个新数组,第一个数组指定每个唯一元素,第二个数组包含每个元素出现的次数。但是,我愿意听取关于输出格式的建议。
例如,如果初始数组是:
5, 5, 5, 2, 2, 2, 2, 2, 9, 4
然后将创建两个新数组。第一个将包含每个唯一元素的名称:
5, 2, 9, 4
第二个将包含该元素在初始数组中出现的次数:
3, 5, 1, 1
因为数字5在初始数组中出现了三次,数字2出现了五次,9和4都出现了一次。
我一直在寻找解决方案,但似乎没有一个可行,而且我自己尝试过的每件事最后都出奇地复杂。任何帮助都将不胜感激!
谢谢:)
返回一个可排序的数组:
let array = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]
let reducedArray = array.reduce( (acc, curr, _, arr) => {
if (acc.length == 0) acc.push({item: curr, count: 1})
else if (acc.findIndex(f => f.item === curr ) === -1) acc.push({item: curr, count: 1})
else ++acc[acc.findIndex(f => f.item === curr)].count
return acc
}, []);
console.log(reducedArray.sort((a,b) => b.count - a.count ))
/*
Output:
[
{
"item": 2,
"count": 5
},
{
"item": 5,
"count": 3
},
{
"item": 9,
"count": 1
},
{
"item": 4,
"count": 1
}
]
*/
不要使用两个数组的结果,使用一个对象:
a = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
result = { };
for(var i = 0; i < a.length; ++i) {
if(!result[a[i]])
result[a[i]] = 0;
++result[a[i]];
}
然后结果将看起来像:
{
2: 5,
4: 1,
5: 3,
9: 1
}
所以这里是我如何做的一些最新的javascript功能:
首先,将数组缩减为一个计数的Map:
let countMap = array.reduce(
(map, value) => {map.set(value, (map.get(value) || 0) + 1); return map},
new Map()
)
通过使用Map,您的起始数组可以包含任何类型的对象,并且计数将是正确的。如果没有Map,某些类型的对象会给你奇怪的计数。
关于区别的更多信息,请参阅Map文档。
如果你所有的值都是符号、数字或字符串,这也可以用在对象上:
let countObject = array.reduce(
(map, value) => { map[value] = (map[value] || 0) + 1; return map },
{}
)
或者使用解构和对象扩展语法,以一种没有突变的函数式方式略显花哨:
let countObject = array.reduce(
(value, {[value]: count = 0, ...rest}) => ({ [value]: count + 1, ...rest }),
{}
)
此时,您可以使用Map或对象进行计数(与对象不同,Map是直接可迭代的),或者将其转换为两个数组。
有关地图:
countMap.forEach((count, value) => console.log(`value: ${value}, count: ${count}`)
let values = countMap.keys()
let counts = countMap.values()
或者对于对象:
Object
.entries(countObject) // convert to array of [key, valueAtKey] pairs
.forEach(([value, count]) => console.log(`value: ${value}, count: ${count}`)
let values = Object.keys(countObject)
let counts = Object.values(countObject)
返回一个可排序的数组:
let array = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]
let reducedArray = array.reduce( (acc, curr, _, arr) => {
if (acc.length == 0) acc.push({item: curr, count: 1})
else if (acc.findIndex(f => f.item === curr ) === -1) acc.push({item: curr, count: 1})
else ++acc[acc.findIndex(f => f.item === curr)].count
return acc
}, []);
console.log(reducedArray.sort((a,b) => b.count - a.count ))
/*
Output:
[
{
"item": 2,
"count": 5
},
{
"item": 5,
"count": 3
},
{
"item": 9,
"count": 1
},
{
"item": 4,
"count": 1
}
]
*/
使用ramda.js有一个更好更简单的方法可以做到这一点。
代码示例
Const ary = [5,5,5,2,2,2,2,2,2,2,2,2,9,4];
R.countBy (r = > r)(必要)
countBy documentation是at documentation