计算数组元素的出现次数/频率
在JavaScript中,我试图获取数字值的初始数组,并计算其中的元素。 理想情况下,结果将是两个新的数组,第一个指定每个唯一的元素,第二个包含每个元素出现的次数。 不过,我接受关于输出格式的build议。
例如,如果最初的数组是:
5, 5, 5, 2, 2, 2, 2, 2, 9, 4
然后创build两个新的数组。 第一个将包含每个唯一元素的名称:
5, 2, 9, 4
第二个将包含元素在初始数组中出现的次数:
3, 5, 1, 1
因为数字5在初始数组中出现三次,所以数字2出现五次,而9和4都出现一次。
我已经search了很多的解决scheme,但似乎没有任何工作,而我自己尝试的一切已经结束了可笑的复杂。 任何帮助将不胜感激!
谢谢 :)
干得好:
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]; }
现场演示: http : //jsfiddle.net/simevidas/bnACW/
您可以使用一个对象来保存结果:
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]);
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}
如果使用下划线或lodash,这是最简单的事情:
_.countBy(array, _.identity);
这样的:
_.countBy([5, 5, 5, 2, 2, 2, 2, 2, 9, 4], _.identity) => Object {2: 5, 4: 1, 5: 3, 9: 1}
正如其他人指出的那样,您可以对结果执行_.keys()
和_.values()
函数,分别得到唯一的数字和它们的出现次数。 但根据我的经验,原来的对象更容易处理。
不要使用两个数组作为结果,使用一个对象:
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]]; }
然后result
将如下所示:
{ 2: 5, 4: 1, 5: 3, 9: 1 }
如何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] ));
aCount.get(5) // 3 aCount.get(2) // 5 aCount.get(9) // 1 aCount.get(4) // 1
此示例将input数组传递给Set
构造函数,以创build唯一值的集合。 扩展语法然后将这些值扩展成一个新的数组,所以我们可以调用map
并将其转换为[value, count]
对的二维数组,即以下结构:
Array [ [5, 3], [2, 5], [9, 1], [4, 1] ]
然后将新的数组传递给Map
构造函数,生成一个可迭代的对象:
Map { 5 => 3, 2 => 5, 9 => 1, 4 => 1 }
关于Map
对象的aCount.get(5)
在于它保留了数据types – 也就是说aCount.get(5)
将返回3
但是aCount.get("5")
将返回undefined
。 它也允许任何值/types作为一个关键的含义,这个解决scheme也将与一系列对象一起工作。
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));
我认为这是最简单的方法如何计数相同的数值发生。
var a = [true, false, false, false]; a.filter(function(value){ return value === false; }).length
如果你喜欢单线。
arr.reduce(function(countMap, word) {countMap[word] = ++countMap[word] || 1;return countMap}, {});
编辑(6/12/2015) :从内到外的解释。 countMap是一个映射一个单词与其频率的映射,我们可以看到匿名函数。 什么减less是应用带有参数的函数作为所有数组元素和countMap作为最后一个函数调用的返回值传递。 最后一个参数({})是第一个函数调用的默认值。
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))
如果你正在使用下划线,你可以去function路线
a = ['foo', 'foo', 'bar']; var results = _.reduce(a,function(counts,key){ counts[key]++; return counts }, _.object( _.map( _.uniq(a), function(key) { return [key, 0] })))
所以你的第一个数组是
_.keys(results)
第二个数组是
_.values(results)
如果可用,大部分这将默认为原生JavaScript函数
演示: http : //jsfiddle.net/dAaUU/
您可以扩展数组原型,如下所示:
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
或者你可以使用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; }
这里只是一些轻而易举的事情
function count(a,i){ var result = 0; for(var o in a) if(a[o] == i) result++; return result; }
编辑:既然你想所有的发生…
function count(a){ var result = {}; for(var i in a){ if(result[a[i]] == undefined) result[a[i]] = 0; result[a[i]]++; } return result; }
基于@adamse和@pmandell (我upvote)的回答 ,在ES6中,你可以在一行中做到这一点 :
- 2017编辑 :我使用
||
以减less代码的大小,使其更具可读性。
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},{}) ));
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};
如果你仍然想要两个数组,那么你可以使用这样的答案 …
var uniqueNums = Object.keys(answer); // uniqueNums => ["2", "4", "5", "9"]; var countOfNums = Object.keys(answer).map(key => answer[key]); // countOfNums => [5, 1, 3, 1];
或者,如果你想uniqueNums是数字
var uniqueNums = Object.keys(answer).map(key => +key); // uniqueNums => [2, 4, 5, 9];
看看下面的代码。
<html> <head> <script> // array with values var ar = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]; var Unique = []; // we'll store a list of unique values in here var Counts = []; // we'll store the number of occurances in here for(var i in ar) { var Index = ar[i]; Unique[Index] = ar[i]; if(typeof(Counts[Index])=='undefined') Counts[Index]=1; else Counts[Index]++; } // remove empty items Unique = Unique.filter(function(){ return true}); Counts = Counts.filter(function(){ return true}); alert(ar.join(',')); alert(Unique.join(',')); alert(Counts.join(',')); var a=[]; for(var i=0; i<Unique.length; i++) { a.push(Unique[i] + ':' + Counts[i] + 'x'); } alert(a.join(', ')); </script> </head> <body> </body> </html>
尝试这个:
Array.prototype.getItemCount = function(item) { var counts = {}; for(var i = 0; i< this.length; i++) { var num = this[i]; counts[num] = counts[num] ? counts[num]+1 : 1; } return counts[item] || 0; }
通过使用count
函数扩展您的数组,可以使这更容易。 它的工作原理就像Rails的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; }
用法:
var array = ['a', 'a', 'b', 'c']; array.count('a'); // => 2 array.count('b'); // => 1 array.count('d'); // => 0 array.count(); // => 4
来源(要点)
给定数组x,即x = ['boy','man','oldman','scout','pilot'];
元素'man'
的出现次数是
x.length - x.toString().split(',man,').toString().split(',').length ;
我正在解决代码的类似问题,并为我devise了以下解决scheme。
这给出了数组中整数的最高数量,也是整数本身。 我认为它也可以应用于string数组。
要正确地对string进行sorting,请从sort()
部分中删除function(a, b){return ab}
function mostFrequentItemCount(collection) { collection.sort(function(a, b){return ab}); var i=0; var ans=[]; var int_ans=[]; while(i<collection.length) { if(collection[i]===collection[i+1]) { int_ans.push(collection[i]); } else { int_ans.push(collection[i]); ans.push(int_ans); int_ans=[]; } i++; } var high_count=0; var high_ans; i=0; while(i<ans.length) { if(ans[i].length>high_count) { high_count=ans[i].length; high_ans=ans[i][0]; } i++; } return high_ans; }
有一个更好更简单的方法,我们可以使用ramda.js
来做到这ramda.js
。 代码示例在这里
const ary = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]; R.countBy(r=> r)(ary)
const ary = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]; R.countBy(r=> r)(ary)
countBy文档在文档中
关于我的评论问@使者关于他的解决scheme的调整。 即时添加我处理它的方式:
let distinctArr = yourArray.filter((curElement, index, array) => array.findIndex(t => t.prop1=== curElement.prop1 && t.prop2 === curElement.prop2 && t.prop3=== curElement.prop3) === index); let distinctWithCount = [...new Set(distinctArr)].map(function(element){element.prop4 = yourArray.filter(t => t.prop1=== element.prop1 && t.prop2 === element.prop2 && t.prop2=== element.prop2).length;
什么我在这里做的是,首先删除重复和保存数组(distinctArr),然后im计算原始数组(yourArray)对象被复制的时间量,并添加第4个属性的值的事件
希望它有助于需要这个具体的解决schemeOfc它是用ES6
这是一种计算对象数组内出现次数的方法。 它还将第一个数组的内容放置在新数组中,以便对值进行sorting,以便原始数组中的顺序不会中断。 然后使用recursion函数遍历每个元素并计数数组内的每个对象的数量属性。
var big_array = [ { name: "Pineapples", quantity: 3 }, { name: "Pineapples", quantity: 1 }, { name: "Bananas", quantity: 1 }, { name: "Limes", quantity: 1 }, { name: "Bananas", quantity: 1 }, { name: "Pineapples", quantity: 2 }, { name: "Pineapples", quantity: 1 }, { name: "Bananas", quantity: 1 }, { name: "Bananas", quantity: 1 }, { name: "Bananas", quantity: 5 }, { name: "Coconuts", quantity: 1 }, { name: "Lemons", quantity: 2 }, { name: "Oranges", quantity: 1 }, { name: "Lemons", quantity: 1 }, { name: "Limes", quantity: 1 }, { name: "Grapefruit", quantity: 1 }, { name: "Coconuts", quantity: 5 }, { name: "Oranges", quantity: 6 } ]; function countThem() { var names_array = []; for (var i = 0; i < big_array.length; i++) { names_array.push( Object.assign({}, big_array[i]) ); } function outerHolder(item_array) { if (item_array.length > 0) { var occurrences = []; var counter = 0; var bgarlen = item_array.length; item_array.sort(function(a, b) { return (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0); }); function recursiveCounter() { occurrences.push(item_array[0]); item_array.splice(0, 1); var last_occurrence_element = occurrences.length - 1; var last_occurrence_entry = occurrences[last_occurrence_element].name; var occur_counter = 0; var quantity_counter = 0; for (var i = 0; i < occurrences.length; i++) { if (occurrences[i].name === last_occurrence_entry) { occur_counter = occur_counter + 1; if (occur_counter === 1) { quantity_counter = occurrences[i].quantity; } else { quantity_counter = quantity_counter + occurrences[i].quantity; } } } if (occur_counter > 1) { var current_match = occurrences.length - 2; occurrences[current_match].quantity = quantity_counter; occurrences.splice(last_occurrence_element, 1); } counter = counter + 1; if (counter < bgarlen) { recursiveCounter(); } } recursiveCounter(); return occurrences; } } alert(JSON.stringify(outerHolder(names_array))); }
ES6版本应该大大简化(另一种解决scheme)
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 }
一个Map而不是普通的Object帮助我们区分不同types的元素,否则所有的计数都是基于string的
这是一个经典的老派计数方法。
var arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]; var counted = [], count = []; var i = 0, j = 0, k = 0; while (k < arr.length) { if (counted.indexOf(arr[k]) < 0) { counted[i] = arr[k]; count[i] = 0; for (j = 0; j < arr.length; j++) { if (counted[i] == arr[j]) { count[i]++; } } i++; } else { k++; } }
如果您想要按字母顺序排列的结果,您可以先对其进行sorting,但是如果要保留input数据的顺序,请尝试一下。 嵌套循环可能比这个页面上的一些其他方法慢一点。