在Javascript中,我试图采取数字值的初始数组,并计算其中的元素。理想情况下,结果将是两个新数组,第一个数组指定每个唯一元素,第二个数组包含每个元素出现的次数。但是,我愿意听取关于输出格式的建议。
例如,如果初始数组是:
5, 5, 5, 2, 2, 2, 2, 2, 9, 4
然后将创建两个新数组。第一个将包含每个唯一元素的名称:
5, 2, 9, 4
第二个将包含该元素在初始数组中出现的次数:
3, 5, 1, 1
因为数字5在初始数组中出现了三次,数字2出现了五次,9和4都出现了一次。
我一直在寻找解决方案,但似乎没有一个可行,而且我自己尝试过的每件事最后都出奇地复杂。任何帮助都将不胜感激!
谢谢:)
不要使用两个数组的结果,使用一个对象:
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
}
给定下面提供的数组:
const array = [ 'a', 'b', 'b', 'c', 'c', 'c' ];
你可以使用这个简单的一行代码来生成一个哈希映射,将一个键链接到它在数组中出现的次数:
const hash = Object.fromEntries([ ...array.reduce((map, key) => map.set(key, (map.get(key) || 0) + 1), new Map()) ]);
// { a: 1, b: 2, c: 3 }
扩展和解释:
// first, we use reduce to generate a map with values and the amount of times they appear
const map = array.reduce((map, key) => map.set(key, (map.get(key) || 0) + 1), new Map())
// next, we spread this map into an array
const table = [ ...map ];
// finally, we use Object.fromEntries to generate an object based on this entry table
const result = Object.fromEntries(table);
这个数组归功于@corashina。减少代码
2021年的版本
更优雅的方法是使用逻辑空赋值(x ??= y)结合数组#reduce()与O(n)时间复杂度。
主要思想仍然是使用array# reduce()将输出作为对象进行聚合,以获得最高的性能(时间和空间复杂度),就像其他答案一样,搜索和构造中间数组。
Const arr = [2,2,2,2,2,2,4,5,5,5,9];
Const result = arr。Reduce ((acc, curr) => {
acc(咕咕叫)? ?= {[curr]: 0};
acc[咕咕叫][咕咕叫]+ +;
返回acc;
}, {});
console.log (Object.values(结果));
清理和重构代码
使用逗号操作符(,)语法。
逗号操作符(,)计算它的每个操作数(从左到右)
右)并返回最后一个操作数的值。
Const arr = [2,2,2,2,2,2,4,5,5,5,9];
Const result = arr。减少((acc,咕咕叫)= > (acc[咕咕叫]= (acc(咕咕叫)| | 0)+ 1,acc), {});
console.log(结果);
输出
{
"2": 5,
"4": 1,
"5": 3,
"9": 1
}
如果使用下划线或lodash,这是最简单的事情:
_.countBy(array);
这样:
_.countBy([5, 5, 5, 2, 2, 2, 2, 2, 9, 4])
=> Object {2: 5, 4: 1, 5: 3, 9: 1}
正如其他人指出的那样,然后可以对结果执行_.keys()和_.values()函数,以分别获得唯一的数字及其出现次数。但根据我的经验,原始对象更容易处理。
Const occurrence =[5,5,5,2,2,2,2,2,2,2,2,2,2,9,4]。Reduce(函数(acc, curr) {
返回acc[curr] ?++acc[curr]: acc[curr] = 1, acc
}, {});
Console.log (occurrences) // => {2: 5,4: 1,5: 3,9: 1}
您可以通过使用count函数扩展数组来简化这一点。它的工作原理类似于Ruby的array# count,如果你熟悉它的话。
Array.prototype.count = function(obj){
var count = this.length;
if(typeof(obj) !== "undefined"){
var array = this.slice(0), count = 0; // clone array and reset count
for(i = 0; i < array.length; i++){
if(array[i] == obj){ count++ }
}
}
return count;
}
用法:
let array = ['a', 'b', 'd', 'a', 'c'];
array.count('a'); // => 2
array.count('b'); // => 1
array.count('e'); // => 0
array.count(); // => 5
Gist
Edit
然后你可以使用array# filter获取你的第一个数组,包含每个出现的项:
let occurred = [];
array.filter(function(item) {
if (!occurred.includes(item)) {
occurred.push(item);
return true;
}
}); // => ["a", "b", "d", "c"]
你的第二个数组,使用数组#count到数组#map:
occurred.map(array.count.bind(array)); // => [2, 1, 1, 1]
或者,如果顺序无关紧要,你可以直接返回一个键值对:
let occurrences = {}
occurred.forEach(function(item) { occurrences[item] = array.count(item) });
occurences; // => {2: 5, 4: 1, 5: 3, 9: 1}