Jac*_*k W 195 javascript arrays element count
在Javascript中,我试图获取一个初始数值值数组并计算其中的元素.理想情况下,结果将是两个新数组,第一个指定每个唯一元素,第二个包含每个元素出现的次数.但是,我愿意接受有关输出格式的建议.
例如,如果初始数组是:
5, 5, 5, 2, 2, 2, 2, 2, 9, 4
Run Code Online (Sandbox Code Playgroud)
然后将创建两个新阵列.第一个将包含每个唯一元素的名称:
5, 2, 9, 4
Run Code Online (Sandbox Code Playgroud)
第二个将包含元素在初始数组中出现的次数:
3, 5, 1, 1
Run Code Online (Sandbox Code Playgroud)
因为数字5在初始数组中出现三次,所以数字2出现五次,9和4出现一次.
我经常搜索一个解决方案,但似乎没有任何工作,我自己尝试过的所有东西都变得荒谬复杂.任何帮助,将不胜感激!
谢谢 :)
typ*_*eof 196
您可以使用对象来保存结果:
var arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
var counts = {};
for (var i = 0; i < arr.length; i++) {
var num = arr[i];
counts[num] = counts[num] ? counts[num] + 1 : 1;
}
console.log(counts[5], counts[2], counts[9], counts[4]);
Run Code Online (Sandbox Code Playgroud)
所以,现在你的计数对象可以告诉你特定数字的计数:
console.log(counts[5]); // logs '3'
Run Code Online (Sandbox Code Playgroud)
如果您想获得一组成员,只需使用这些keys()
功能即可
keys(counts); // returns ["5", "2", "9", "4"]
Run Code Online (Sandbox Code Playgroud)
Šim*_*das 87
干得好:
function foo(arr) {
var a = [], b = [], prev;
arr.sort();
for ( var i = 0; i < arr.length; i++ ) {
if ( arr[i] !== prev ) {
a.push(arr[i]);
b.push(1);
} else {
b[b.length-1]++;
}
prev = arr[i];
}
return [a, b];
}
Run Code Online (Sandbox Code Playgroud)
现场演示: http ://jsfiddle.net/simevidas/bnACW/
注意
这会改变原始输入数组的顺序
Array.sort
ada*_*mse 81
var a = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4].reduce(function (acc, curr) {
if (typeof acc[curr] == 'undefined') {
acc[curr] = 1;
} else {
acc[curr] += 1;
}
return acc;
}, {});
// a == {2: 5, 4: 1, 5: 3, 9: 1}
Run Code Online (Sandbox Code Playgroud)
rad*_*and 70
如果使用下划线或lodash,这是最简单的事情:
_.countBy(array);
Run Code Online (Sandbox Code Playgroud)
这样:
_.countBy([5, 5, 5, 2, 2, 2, 2, 2, 9, 4])
=> Object {2: 5, 4: 1, 5: 3, 9: 1}
Run Code Online (Sandbox Code Playgroud)
正如其他人所指出的那样,您可以在结果上执行_.keys()
和_.values()
函数,以分别获得唯一的数字及其出现次数.但根据我的经验,原始对象更容易处理.
mu *_*ort 53
不要使用两个数组作为结果,使用一个对象:
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]];
}
Run Code Online (Sandbox Code Playgroud)
然后result
会看起来像:
{
2: 5,
4: 1,
5: 3,
9: 1
}
Run Code Online (Sandbox Code Playgroud)
Emi*_*ary 37
ECMAScript2015选项怎么样?
const a = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
const aCount = new Map([...new Set(a)].map(
x => [x, a.filter(y => y === x).length]
));
Run Code Online (Sandbox Code Playgroud)
aCount.get(5) // 3
aCount.get(2) // 5
aCount.get(9) // 1
aCount.get(4) // 1
Run Code Online (Sandbox Code Playgroud)
此示例将输入数组传递给Set
构造函数,从而创建唯一值的集合.该价差语法则扩展了这些值到一个新的数组,所以我们可以调用map
并转化为一个二维数组这[value, count]
对-即结构如下:
Array [
[5, 3],
[2, 5],
[9, 1],
[4, 1]
]
Run Code Online (Sandbox Code Playgroud)
Map {
5 => 3,
2 => 5,
9 => 1,
4 => 1
}
Run Code Online (Sandbox Code Playgroud)
关于Map
对象的好处是它保留了数据类型 - 也就是说aCount.get(5)
将返回3
但aCount.get("5")
将返回undefined
.它还允许任何值/类型作为键,这意味着此解决方案也可以使用一组对象.
function frequencies(/* {Array} */ a){
return new Map([...new Set(a)].map(
x => [x, a.filter(y => y === x).length]
));
}
let foo = { value: 'foo' },
bar = { value: 'bar' },
baz = { value: 'baz' };
let aNumbers = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4],
aObjects = [foo, bar, foo, foo, baz, bar];
frequencies(aNumbers).forEach((val, key) => console.log(key + ': ' + val));
frequencies(aObjects).forEach((val, key) => console.log(key.value + ': ' + val));
Run Code Online (Sandbox Code Playgroud)
小智 34
我认为这是如何计算数组中具有相同值的事件的最简单方法.
var a = [true, false, false, false];
a.filter(function(value){
return value === false;
}).length
Run Code Online (Sandbox Code Playgroud)
Vla*_*den 27
const data = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]
function count(arr) {
return arr.reduce((prev, curr) => (prev[curr] = ++prev[curr] || 1, prev), {})
}
console.log(count(data))
Run Code Online (Sandbox Code Playgroud)
rja*_*lfa 20
如果您喜欢单个衬垫.
arr.reduce(function(countMap, word) {countMap[word] = ++countMap[word] || 1;return countMap}, {});
编辑(2015年12月6日):由内而外的解释.countMap是一个映射单词及其频率的映射,我们可以看到匿名函数.reduce的作用是将带有参数的函数应用为所有数组元素和countMap作为最后一个函数调用的返回值传递.最后一个参数({})是第一个函数调用的countMap的默认值.
Ngu*_*ong 16
Logical nullish assignment (x ??= y)
结合Array#reduce()
O(n) 时间复杂度使用。其主要思想仍然使用Array#reduce()
与输出聚集为object
以获得最高的性能(时间和空间复杂度)中的条款searching
和construct bunches of intermediate arrays
像其他的答案。
const arr = [2, 2, 2, 2, 2, 4, 5, 5, 5, 9];
const result = arr.reduce((acc, curr) => {
acc[curr] ??= {[curr]: 0};
acc[curr][curr]++;
return acc;
}, {});
console.log(Object.values(result));
Run Code Online (Sandbox Code Playgroud)
使用逗号运算符 (,)语法。
The comma operator (,)
计算其每个操作数(从左到右)并返回最后一个操作数的值。
const arr = [2, 2, 2, 2, 2, 4, 5, 5, 5, 9];
const result = arr.reduce((acc, curr) => (acc[curr] = (acc[curr] || 0) + 1, acc), {});
console.log(result);
Run Code Online (Sandbox Code Playgroud)
输出
{
"2": 5,
"4": 1,
"5": 3,
"9": 1
}
Run Code Online (Sandbox Code Playgroud)
Wil*_*ung 15
ES6版本应该是更简化(另一个行解决方案)
let arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
let acc = arr.reduce((acc, val) => acc.set(val, 1 + (acc.get(val) || 0)), new Map());
console.log(acc);
// output: Map { 5 => 3, 2 => 5, 9 => 1, 4 => 1 }
Run Code Online (Sandbox Code Playgroud)
Map而不是plain Object帮助我们区分不同类型的元素,或者所有计数都基于字符串
Pen*_*Liu 11
reduce
使用and tilde( ~
) 运算符的较短版本。
const data = [2, 2, 2, 2, 2, 4, 5, 5, 5, 9];
function freq(nums) {
return nums.reduce((acc, curr) => {
acc[curr] = -~acc[curr];
return acc;
}, {});
}
console.log(freq(data));
Run Code Online (Sandbox Code Playgroud)
小智 8
如果您使用下划线,您可以使用功能路线
a = ['foo', 'foo', 'bar'];
var results = _.reduce(a,function(counts,key){ counts[key]++; return counts },
_.object( _.map( _.uniq(a), function(key) { return [key, 0] })))
Run Code Online (Sandbox Code Playgroud)
所以你的第一个阵列是
_.keys(results)
Run Code Online (Sandbox Code Playgroud)
第二个数组是
_.values(results)
Run Code Online (Sandbox Code Playgroud)
如果它们可用,大部分将默认为本机javascript函数
一线ES6解决方案。使用对象作为地图的答案如此之多,但我看不到有人使用实际的地图
const map = arr.reduce((acc, e) => acc.set(e, (acc.get(e) || 0) + 1), new Map());
Run Code Online (Sandbox Code Playgroud)
使用map.keys()
获得独特的元素
使用map.values()
来获取事件
使用map.entries()
以获得对[元件,频率]
我参加聚会有点晚了,但我希望至少有人会有所帮助。
const map = arr.reduce((acc, e) => acc.set(e, (acc.get(e) || 0) + 1), new Map());
Run Code Online (Sandbox Code Playgroud)
基于答案的@adamse和@pmandell(我给予好评),在ES6你能做到这一点的一条线:
||
用来减少代码大小并使其更具可读性.var a=[7,1,7,2,2,7,3,3,3,7,,7,7,7];
alert(JSON.stringify(
a.reduce((r,k)=>{r[k]=1+r[k]||1;return r},{})
));
Run Code Online (Sandbox Code Playgroud)
它可以用来计算字符数:
var s="ABRACADABRA";
alert(JSON.stringify(
s.split('').reduce((a, c)=>{a[c]++?0:a[c]=1;return a},{})
));
Run Code Online (Sandbox Code Playgroud)
使用时间复杂度为O(n)的映射的解决方案。
var arr = [2, 2, 2, 2, 2, 4, 5, 5, 5, 9];
const countOccurrences = (arr) => {
const map = {};
for ( var i = 0; i < arr.length; i++ ) {
map[arr[i]] = ~~map[arr[i]] + 1;
}
return map;
}
Run Code Online (Sandbox Code Playgroud)
演示: http: //jsfiddle.net/simvidas/bnACW/
您可以扩展Array原型,如下所示:
Array.prototype.frequencies = function() {
var l = this.length, result = {all:[]};
while (l--){
result[this[l]] = result[this[l]] ? ++result[this[l]] : 1;
}
// all pairs (label, frequencies) to an array of arrays(2)
for (var l in result){
if (result.hasOwnProperty(l) && l !== 'all'){
result.all.push([ l,result[l] ]);
}
}
return result;
};
var freqs = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4].frequencies();
alert(freqs[2]); //=> 5
// or
var freqs = '1,1,2,one,one,2,2,22,three,four,five,three,three,five'
.split(',')
.frequencies();
alert(freqs.three); //=> 3
Run Code Online (Sandbox Code Playgroud)
或者你可以利用Array.map
:
Array.prototype.frequencies = function () {
var freqs = {sum: 0};
this.map( function (a){
if (!(a in this)) { this[a] = 1; }
else { this[a] += 1; }
this.sum += 1;
return a; }, freqs
);
return freqs;
}
Run Code Online (Sandbox Code Playgroud)
这里只是一些轻松易用的东西......
function count(a,i){
var result = 0;
for(var o in a)
if(a[o] == i)
result++;
return result;
}
Run Code Online (Sandbox Code Playgroud)
编辑:因为你想要所有的出现......
function count(a){
var result = {};
for(var i in a){
if(result[a[i]] == undefined) result[a[i]] = 0;
result[a[i]]++;
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
var array = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
function countDuplicates(obj, num){
obj[num] = (++obj[num] || 1);
return obj;
}
var answer = array.reduce(countDuplicates, {});
// answer => {2:5, 4:1, 5:3, 9:1};
Run Code Online (Sandbox Code Playgroud)
如果你仍然想要两个数组,那么你可以使用这样的答案......
var uniqueNums = Object.keys(answer);
// uniqueNums => ["2", "4", "5", "9"];
var countOfNums = Object.keys(answer).map(key => answer[key]);
// countOfNums => [5, 1, 3, 1];
Run Code Online (Sandbox Code Playgroud)
或者,如果您希望 uniqueNums 是数字
var uniqueNums = Object.keys(answer).map(key => +key);
// uniqueNums => [2, 4, 5, 9];
Run Code Online (Sandbox Code Playgroud)
So here's how I'd do it with some of the newest javascript features:
First, reduce the array to a Map
of the counts:
let countMap = array.reduce(
(map, value) => {map.set(value, (map.get(value) || 0) + 1); return map},
new Map()
)
Run Code Online (Sandbox Code Playgroud)
通过使用Map
,起始数组可以包含任何类型的对象,并且计数将是正确的。如果不使用Map
,则某些类型的对象会给您带来奇怪的计数。有关差异的更多信息,请参阅Map
文档。
如果您所有的值都是符号,数字或字符串,则也可以使用一个对象来完成此操作:
let countObject = array.reduce(
(map, value) => { map[value] = (map[value] || 0) + 1; return map },
{}
)
Run Code Online (Sandbox Code Playgroud)
或者使用解构和对象散布语法以某种功能性稍稍稍稍变而无变化:
let countObject = array.reduce(
(value, {[value]: count = 0, ...rest}) => ({ [value]: count + 1, ...rest }),
{}
)
Run Code Online (Sandbox Code Playgroud)
此时,您可以将Map
or对象用于计数(与对象不同,地图可以直接迭代),或将其转换为两个数组。
对于Map
:
countMap.forEach((count, value) => console.log(`value: ${value}, count: ${count}`)
let values = countMap.keys()
let counts = countMap.values()
Run Code Online (Sandbox Code Playgroud)
或针对对象:
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)
Run Code Online (Sandbox Code Playgroud)