获取数组中出现次数最多的项

Posted

技术标签:

【中文标题】获取数组中出现次数最多的项【英文标题】:Get the item that appears the most times in an array 【发布时间】:2011-04-16 14:02:33 【问题描述】:
var store = ['1','2','2','3','4'];

我想知道2 在数组中出现的次数最多。我该怎么做呢?

【问题讨论】:

该数组是否总是排序的(就像在您的示例中一样)? 查看我的伪代码答案:***.com/questions/3774757/… 如果@Thilo 的问题的答案是肯定的,相同的元素将始终组合在一起。这允许您在将每个项目与前一个项目进行比较后遍历列表,并记录您遇到的相同元素的数量以及一路上遇到的最高运行次数。在循环结束时,您将得到答案。这将在线性时间内运行。如果@Thilo 的问题的答案是否定的,那么首先对列表进行排序,然后是上面的策略。 @Asaph:如果数组没有排序,codaddict的算法比排序好(如果你可以为频率计数器腾出额外的内存) @Thilo:是的。它好一点。但是排序并不是那么大的开销。 @codaddict 的算法在线性空间和线性时间中运行。我的建议在恒定空间和 O(n log n + n) 时间内运行,具体取决于排序算法。 【参考方案1】:

我会这样做:

var store = ['1','2','2','3','4'];
var frequency = ;  // array of frequency.
var max = 0;  // holds the max frequency.
var result;   // holds the max frequency element.
for(var v in store) 
        frequency[store[v]]=(frequency[store[v]] || 0)+1; // increment frequency.
        if(frequency[store[v]] > max)  // is this frequency > max so far ?
                max = frequency[store[v]];  // update max.
                result = store[v];          // update result.
        

【讨论】:

+1 - 非常好...但我会使用for 循环来阻止数组对象具有属性的极端情况:jsfiddle.net/9eJd3 我建议添加if (store.hasOwnProperty(v)),以防有人决定修改 Object 或 Array 的原型,因为人们似乎有点热衷于在这里做这件事;P @no - 这还不够好,因为store 可以拥有自己的属性,而这些属性不是数组的值。 (jsfiddle.net/vR5JK)。 for 循环可以解决问题,因为数组中的值之外的任何内容都不包含在 store[0]store[store.length] 糟糕,for 循环我的意思是 for(var v=0; v < store.length; ++v)... @Peter Ajtai - 我看到了你的例子,但这实际上是我所期望的行为......我希望数组对象的每个属性都计算在内,无论该属性是否也代表数组索引。这样它也可以用于常规对象。我想这取决于你想要什么行为。【参考方案2】:

Array.prototype.forEach 为重点的解决方案,以及如果在更多项目之间共享最大计数时获得多个密钥的问题。

编辑:只有一个循环的提案。

var store = ['1', '2', '2', '3', '4', '5', '5'],
    distribution = ,
    max = 0,
    result = [];

store.forEach(function (a) 
    distribution[a] = (distribution[a] || 0) + 1;
    if (distribution[a] > max) 
        max = distribution[a];
        result = [a];
        return;
    
    if (distribution[a] === max) 
        result.push(a);
    
);
console.log('max: ' + max);
console.log('key/s with max count: ' + JSON.stringify(result));
console.log(distribution);

【讨论】:

【参考方案3】:
arr.sort();
    var max=0,result,freq = 0;
    for(var i=0; i < arr.length; i++)
        if(arr[i]===arr[i+1])
            freq++;
        
        else 
            freq=0;
        
        if(freq>max)
            result = arr[i];
            max = freq;
        
    
    return result;

【讨论】:

由于有许多其他答案,添加解释为什么您的解决方案更可取可能会有所帮助。您可以通过单击“编辑”按钮添加说明... arr.sort() 是否总是对数组中不同类型的组进行正确排序? 是的@user2734550。 arr.sort() 能够正确排序数组中不同类型的组。但如果你正在处理单个数字和多个数字,你可能需要这样排序: arr.sort(function(a,b)return a- b;) 谢谢。我真的很喜欢你的解决方案!易于阅读且易于理解。也适用于字符串。 我喜欢您的解决方案,因为它使用了大多数 C 系列语言通用的基本 javascript 指令。【参考方案4】:

制作直方图,找出直方图中最大数的key。

var hist = [];
for (var i = 0; i < store.length; i++) 
  var n = store[i];
  if (hist[n] === undefined) hist[n] = 0;
  else hist[n]++;


var best_count = hist[store[0]];
var best = store[0];
for (var i = 0; i < store.length; i++) 
  if (hist[store[i]] > best_count) 
    best_count = hist[store[i]];
    best = store[i];
  


alert(best + ' occurs the most at ' + best_count + ' occurrences');

这假设要么没有关系,要么你不在乎选择了哪个。

【讨论】:

不过,如果数组已排序,则不需要。那么它可以是一个单遍操作。 附带说明,这称为分发模式。【参考方案5】:

如果数组已排序,这应该可以:

function popular(array)  
   if (array.length == 0) return [null, 0];
   var n = max = 1, maxNum = array[0], pv, cv;

   for(var i = 0; i < array.length; i++, pv = array[i-1], cv = array[i]) 
      if (pv == cv)  
        if (++n >= max) 
           max = n; maxNum = cv;
        
       else n = 1;
   

   return [maxNum, max];
;

popular([1,2,2,3,4,9,9,9,9,1,1])
[9, 4]

popular([1,2,2,3,4,9,9,9,9,1,1,10,10,10,10,10])
[10, 5]

【讨论】:

这些值不需要排序,只是分组。如果检查当前候选模式的频率if (pv != cv),则比较少。 @greybeard,arr.sort() 能很好地“分组”吗?我知道它对不同类型的排序不太好,但它是否正确分组?【参考方案6】:

当计数超过尚未计数的项目数时,此版本将退出查找。

它无需对数组进行排序即可工作。

Array.prototype.most= function()
    var L= this.length, freq= [], unique= [], 
    tem, max= 1, index, count;
    while(L>= max)
        tem= this[--L];
        if(unique.indexOf(tem)== -1)
            unique.push(tem);
            index= -1, count= 0;
            while((index= this.indexOf(tem, index+1))!= -1)
                ++count;
            
            if(count> max)
                freq= [tem];
                max= count;
            
            else if(count== max) freq.push(tem);
        
    
    return [freq, max];


    //test
    var A= ["apples","oranges","oranges","oranges","bananas",
   "bananas","oranges","bananas"];
    alert(A.most()) // [oranges,4]

    A.push("bananas");
    alert(A.most()) // [bananas,oranges,4]

【讨论】:

【参考方案7】:

我用这种方法解决了寻找最常见的整数

function mostCommon(arr) 
    // finds the first most common integer, doesn't account for 2 equally common integers (a tie)

    freq = [];

    // set all frequency counts to 0
    for(i = 0; i < arr[arr.length-1]; i++) 
      freq[i] = 0;
    

    // use index in freq to represent the number, and the value at the index represent the frequency count 
    for(i = 0; i < arr.length; i++) 
      freq[arr[i]]++; 
    

    // find biggest number's index, that's the most frequent integer
    mostCommon = freq[0];
    for(i = 0; i < freq.length; i++) 
      if(freq[i] > mostCommon) 
        mostCommon = i;
      
    

    return mostCommon;
 

【讨论】:

【参考方案8】:

这是我的解决方案。

var max_frequent_elements = function(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];



var max = b[0]
for(var p=1;p<b.length;p++)
       if(b[p]>max)max=b[p]
 

var indices = []
for(var q=0;q<a.length;q++)
   if(b[q]==max)indices.push(a[q])

return indices;

;

【讨论】:

【参考方案9】:

以上所有解决方案都是迭代的。

这是一个 ES6 功能无突变版本:

Array.prototype.mostRepresented = function() 
  const indexedElements = this.reduce((result, element) => 
    return result.map(el => 
      return 
        value: el.value,
        count: el.count + (el.value === element ? 1 : 0),
      ;
    ).concat(result.some(el => el.value === element) ? [] : value: element, count: 1);
  , []);
  return (indexedElements.slice(1).reduce(
    (result, indexedElement) => (indexedElement.count > result.count ? indexedElement : result),
    indexedElements[0]) || ).value;
;

它可以在性能成为瓶颈的特定情况下进行优化,但它在处理任何类型的数组元素方面具有很大优势。

最后一行可以替换为:

  return (indexedElements.maxBy(el => el.count) || ).value;

与:

Array.prototype.maxBy = function(fn) 
  return this.slice(1).reduce((result, element) => (fn(element) > fn(result) ? element : result), this[0]);
;

为了清楚

【讨论】:

【参考方案10】:

如果数组包含字符串,试试这个解决方案

    function GetMaxFrequency (array) 
    var store = array;
    var frequency = [];  // array of frequency.
    var result;   // holds the max frequency element.

    for(var v in store) 
        var target = store[v];
        var numOccurences = $.grep(store, function (elem) 
        return elem === target;
        ).length;
        frequency.push(numOccurences);

    
    maxValue = Math.max.apply(this, frequency);
    result = store[$.inArray(maxValue,frequency)];
    return result;

var store = ['ff','cc','cc','ff','ff','ff','ff','ff','ff','yahya','yahya','cc','yahya'];
alert(GetMaxFrequency(store));

【讨论】:

【参考方案11】:

一个相当简短的解决方案。

function mostCommon(list) 
  var keyCounts = ;
  var topCount = 0;
  var topKey = ;
  list.forEach(function(item, val) 
    keyCounts[item] = keyCounts[item] + 1 || 1;
    if (keyCounts[item] > topCount) 
      topKey = item;
      topCount = keyCounts[item];
    
  );

  return topKey;


document.write(mostCommon(['AA', 'AA', 'AB', 'AC']))

【讨论】:

【参考方案12】:

此解决方案返回一个数组中出现次数最多的数字,以防多个数字出现在“最大”次。

    function mode(numbers) 
      var counterObj = ; 
      var max = 0;
      var result = [];
      for(let num in numbers) 
        counterObj[numbers[num]] = (counterObj[numbers[num]] || 0) + 1; 
        if(counterObj[numbers[num]] >= max)  
          max = counterObj[numbers[num]];
        
      
      for (let num in counterObj) 
        if(counterObj[num] == max) 
          result.push(parseInt(num));
        
      
      return result;
    

【讨论】:

以上是关于获取数组中出现次数最多的项的主要内容,如果未能解决你的问题,请参考以下文章

获取数组中出现次数最多的数据及出现次数

获取在一个数组中出现最多的字符及其所在的位置

js - 获取字符串出现最多的字符和次数

读取一个文件,获取其中出现次数最多的前五个字符以及次数

获取页面中出现次数最多的三个标签以及出现次数

获取字符串中出现次数最多的字母