计算数组元素的出现次数/频率

在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数据的顺序,请尝试一下。 嵌套循环可能比这个页面上的一些其他方法慢一点。