获取数组中出现次数最多的元素

我正在寻找一个优雅的方式来确定哪个元素在JavaScript数组中具有最高的出现次数( 模式 )。

例如,在

['pear', 'apple', 'orange', 'apple'] 

'apple'元素是最常见'apple'元素。

这只是模式。 这是一个快速,非优化的解决scheme。 应该是O(n)。

 function mode(array) { if(array.length == 0) return null; var modeMap = {}; var maxEl = array[0], maxCount = 1; for(var i = 0; i < array.length; i++) { var el = array[i]; if(modeMap[el] == null) modeMap[el] = 1; else modeMap[el]++; if(modeMap[el] > maxCount) { maxEl = el; maxCount = modeMap[el]; } } return maxEl; } 

根据George Jempty's提出的algorithm来解决关系问题,我提出了Matthew Flaschen'salgorithm的修改版本。

 function modeString(array) { if (array.length == 0) return null; var modeMap = {}, maxEl = array[0], maxCount = 1; for(var i = 0; i < array.length; i++) { var el = array[i]; if (modeMap[el] == null) modeMap[el] = 1; else modeMap[el]++; if (modeMap[el] > maxCount) { maxEl = el; maxCount = modeMap[el]; } else if (modeMap[el] == maxCount) { maxEl += '&' + el; maxCount = modeMap[el]; } } return maxEl; } 

这将返回一个由'&'符号分隔的模式元素的string。 当收到结果时,可以将该结果拆分为'&'元素,并且具有您的模式。

另一个select是返回一个模式元素的数组,像这样:

 function modeArray(array) { if (array.length == 0) return null; var modeMap = {}, maxCount = 1, modes = [array[0]]; for(var i = 0; i < array.length; i++) { var el = array[i]; if (modeMap[el] == null) modeMap[el] = 1; else modeMap[el]++; if (modeMap[el] > maxCount) { modes = [el]; maxCount = modeMap[el]; } else if (modeMap[el] == maxCount) { modes.push(el); maxCount = modeMap[el]; } } return modes; } 

在上面的例子中,您将能够将该函数的结果作为模式数组处理。

自从2009年以来,JavaScript已经有了一些发展 – 我想我会再添加一个选项。 我很less关心效率,直到实际上是一个问题,所以我对“优雅”代码的定义(按照OP的规定)有利于可读性 – 这当然是主观的。

 function mode(arr){ return arr.sort((a,b) => arr.filter(v => v===a).length - arr.filter(v => v===b).length ).pop(); } mode(['pear', 'apple', 'orange', 'apple']); // apple 

在这个特定的例子中,如果该集合中的两个或多个元素具有相同的出现次数,那么将返回出现在数组中最近的元素。 还值得指出的是,它会修改你的原始数组 – 如果你希望事先使用Array.slice调用,可以防止这种Array.slice


编辑:更新了一些ES6 胖箭头的例子,因为2015年发生,我认为他们看起来很漂亮…如果你关心向后兼容性,你可以在修订历史中find这个。

 a = ['梨','苹果','橙','苹果'];
 B = [];
 max ='',maxi = 0;
 for(var k in a){
   if(b [k])b [k] ++ else b [k] = 1;
   if(maxi <b [k]){max = k;  maxi = b [k]}
 }

这个解决scheme可以返回一个数组的多个元素,如果它们发生在同一时间。 例如,一个数组arr = [3,4,3,6,4]有两个模式值3和6。

这是解决scheme,

 function find_mode(arr) { var max = 0; var maxarr = []; var counter = []; var maxarr = []; arr.forEach(function(){ counter.push(0); }); for(var i = 0;i<arr.length;i++){ for(var j=0;j<arr.length;j++){ if(arr[i]==arr[j])counter[i]++; } } max=this.arrayMax(counter); for(var i = 0;i<arr.length;i++){ if(counter[i]==max)maxarr.push(arr[i]); } var unique = maxarr.filter( this.onlyUnique ); return unique; }; function arrayMax(arr) { var len = arr.length, max = -Infinity; while (len--) { if (arr[len] > max) { max = arr[len]; } } return max; }; function onlyUnique(value, index, self) { return self.indexOf(value) === index; } 

基于Emissary的ES6 +答案,你可以使用Array.prototype.reduce来进行比较(而不是sorting,popup和可能改变你的数组),我认为这看起来很光滑。

 const mode = (myArray) => myArray.reduce( (a,b,i,arr)=> (arr.filter(v=>v===a).length>=arr.filter(v=>v===b).length?a:b), null) 

我默认为null,如果null是一个可能的选项,你会过滤,这不会总是给你一个真实的答案,也许这可能是一个可选的第二个参数

与其他各种解决scheme一样,缺点是它不能处理“绘制状态”,但是仍然可以通过略微涉及的减lessfunction来实现。

 var mode = 0; var c = 0; var num = new Array(); var value = 0; var greatest = 0; var ct = 0; 

注意:ct是数组的长度。

 function getMode() { for (var i = 0; i < ct; i++) { value = num[i]; if (i != ct) { while (value == num[i + 1]) { c = c + 1; i = i + 1; } } if (c > greatest) { greatest = c; mode = value; } c = 0; } } 

时间另一种解决scheme:

 function getMaxOccurrence(arr) { var o = {}, maxCount = 0, maxValue, m; for (var i=0, iLen=arr.length; i<iLen; i++) { m = arr[i]; if (!o.hasOwnProperty(m)) { o[m] = 0; } ++o[m]; if (o[m] > maxCount) { maxCount = o[m]; maxValue = m; } } return maxValue; } 

如果简洁(事实并非如此),那么:

 function getMaxOccurrence(a) { var o = {}, mC = 0, mV, m; for (var i=0, iL=a.length; i<iL; i++) { m = a[i]; o.hasOwnProperty(m)? ++o[m] : o[m] = 1; if (o[m] > mC) mC = o[m], mV = m; } return mV; } 

如果要避免不存在的成员(例如稀疏数组),则需要额外的hasOwnPropertytesting:

 function getMaxOccurrence(a) { var o = {}, mC = 0, mV, m; for (var i=0, iL=a.length; i<iL; i++) { if (a.hasOwnProperty(i)) { m = a[i]; o.hasOwnProperty(m)? ++o[m] : o[m] = 1; if (o[m] > mC) mC = o[m], mV = m; } } return mV; } getMaxOccurrence([,,,,,1,1]); // 1 

这里的其他答案将返回undefined

 function mode(arr){ return arr.reduce(function(counts,key){ var curCount = (counts[key+''] || 0) + 1; counts[key+''] = curCount; if (curCount > counts.max) { counts.max = curCount; counts.mode = key; } return counts; }, {max:0, mode: null}).mode } 

在这里尝试一个声明式的方法。 这个解决scheme构build了一个对象来统计每个单词的出现次数。 然后通过将每个单词的总出现次数与对象中find的最高值进行比较,将对象过滤为数组。

 const arr = ['hello', 'world', 'hello', 'again']; const tally = (acc, x) => { if (! acc[x]) { acc[x] = 1; return acc; } acc[x] += 1; return acc; }; const totals = arr.reduce(tally, {}); const keys = Object.keys(totals); const values = keys.map(x => totals[x]); const results = keys.filter(x => totals[x] === Math.max(...values)); 

这是我对这个问题的解决scheme,但有数字和使用新的“设置”function。 它不是很高性能,但我写了这个确实有很多乐趣,它支持多个最大值。

 const mode = (arr) => [...new Set(arr)] .map((value) => [value, arr.filter((v) => v === value).length]) .sort((a,b) => a[1]-b[1]) .reverse() .filter((value, i, a) => a.indexOf(value) === i) .filter((v, i, a) => v[1] === a[0][1]) .map((v) => v[0]) mode([1,2,3,3]) // [3] mode([1,1,1,1,2,2,2,2,3,3,3]) // [1,2] 

顺便说一句,不要使用这个生产这只是一个说明如何才能解决它与ES6和arraysfunction只。

这是我的解决scheme:

 function frequent(number){ var count = 0; var sortedNumber = number.sort(); var start = number[0], item; for(var i = 0 ; i < sortedNumber.length; i++){ if(start === sortedNumber[i] || sortedNumber[i] === sortedNumber[i+1]){ item = sortedNumber[i] } } return item } console.log( frequent(['pear', 'apple', 'orange', 'apple'])) 

试试吧,这不考虑浏览器版本。

 function mode(arr){ var a = [],b = 0,occurrence; for(var i = 0; i < arr.length;i++){ if(a[arr[i]] != undefined){ a[arr[i]]++; }else{ a[arr[i]] = 1; } } for(var key in a){ if(a[key] > b){ b = a[key]; occurrence = key; } } return occurrence; } alert(mode(['segunda','terça','terca','segunda','terça','segunda'])); 

请注意,当2个或更多的条目出现相同的次数时,这个函数返回数组中的最新发生!

我想你有两种方法。 两者都有优势。

然后sorting计数或循环,并使用哈希表来为你做计数。

散列表很好,因为一旦你完成处理,你也有所有不同的元素。 如果你有几百万个项目,如果重复率很低,哈希表可能会使用大量的内存。 sorting,然后计数的方法将有一个更可控的内存占用。

 var array = [1, 3, 6, 6, 6, 6, 7, 7, 12, 12, 17], c = {}, // counters s = []; // sortable array for (var i=0; i<array.length; i++) { c[array[i]] = c[array[i]] || 0; // initialize c[array[i]]++; } // count occurrences for (var key in c) { s.push([key, c[key]]) } // build sortable array from counters s.sort(function(a, b) {return b[1]-a[1];}); var firstMode = s[0][0]; console.log(firstMode); 

你可以试试这个:

  // using splice() // get the element with the highest occurence in an array function mc(a) { var us = [], l; // find all the unique elements in the array a.forEach(function (v) { if (us.indexOf(v) === -1) { us.push(v); } }); l = us.length; while (true) { for (var i = 0; i < l; i ++) { if (a.indexOf(us[i]) === -1) { continue; } else if (a.indexOf(us[i]) != -1 && a.length > 1) { // just delete it once at a time a.splice(a.indexOf(us[i]), 1); } else { // default to last one return a[0]; } } } } // using string.match method function su(a) { var s = a.join(), uelms = [], r = {}, l, i, m; a.forEach(function (v) { if (uelms.indexOf(v) === -1) { uelms.push(v); } }); l = uelms.length; // use match to calculate occurance times for (i = 0; i < l; i ++) { r[uelms[i]] = s.match(new RegExp(uelms[i], 'g')).length; } m = uelms[0]; for (var p in r) { if (r[p] > r[m]) { m = p; } else { continue; } } return m; } 

你可以用O(n)的复杂性来解决它

 var arr = [1,3,54,56,6,6,1,6]; var obj = {}; /* first convert the array in to object with unique elements and number of times each element is repeated */ for(var i = 0; i < arr.length; i++) { var x = arr[i]; if(!obj[x]) obj[x] = 1; else obj[x]++; } console.log(obj);//just for reference /* now traverse the object to get the element */ var index = 0; var max = 0; for(var obIndex in obj) { if(obj[obIndex] > max) { max = obj[obIndex]; index = obIndex; } } console.log(index+" got maximum time repeated, with "+ max +" times" ); 

只需复制并粘贴到Chrome控制台即可运行上述代码。

这个函数是每种types信息的通用函数。 它计算元素的出现,然后返回具有最大出现元素的数组。

 function mode () { var arr = [].slice.call(arguments); if ((args.length == 1) && (typeof args[0] === "object")) { args = args[0].mode(); } var obj = {}; for(var i = 0; i < arr.length; i++) { if(obj[arr[i]] === undefined) obj[arr[i]] = 1; else obj[arr[i]]++; } var max = 0; for (w in obj) { if (obj[w] > max) max = obj[w]; } ret_val = []; for (w in obj) { if (obj[w] == max) ret_val.push(w); } return ret_val; } 
 const mode = (str) => { return str .split(' ') .reduce((data, key) => { let counter = data.map[key] + 1 || 1 data.map[key] = counter if (counter > data.counter) { data.counter = counter data.mode = key } return data }, { counter: 0, mode: null, map: {} }) .mode } console.log(mode('the t-rex is the greatest of them all')) 
 function mode(){ var input = $("input").val().split(","); var mode = []; var m = []; var p = []; for(var x = 0;x< input.length;x++){ if(m.indexOf(input[x])==-1){ m[m.length]=input[x]; }} for(var x = 0; x< m.length;x++){ p[x]=0; for(var y = 0; y<input.length;y++){ if(input[y]==m[x]){ p[x]++; }}} for(var x = 0;x< p.length;x++){ if(p[x] ==(Math.max.apply(null, p))){ mode.push(m[x]); }} $("#output").text(mode);} 
 function mode(array){ var set = Array.from(new Set(array)); var counts = set.map(a=>array.filter(b=>b==a).length); var indices = counts.map((a,b)=>Math.max(...counts)===a?b:0).filter(b=>b!==0); var mode = indices.map(a=>set[a]); return mode; }