javascript 查找数组中出现频率最高的项(不仅仅是字符串)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31227687/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 13:29:59  来源:igfitidea点击:

Find the most frequent item of an array (not just strings)

javascriptarraysalgorithm

提问by chichi

Can someone walk me through this exercise? Write a JavaScript program to find the most frequent item of an array.

有人可以指导我完成这个练习吗?编写一个 JavaScript 程序来查找数组中最频繁的项。

var arr1 = [3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3];
var mf = 1;
var m = 0;
var item;

for (var i = 0; i < arr1.length; i++) {
  for (var j = i; j < arr1.length; j++) {
    if (arr1[i] == arr1[j]) m++;
    if (mf < m) {
      mf = m;
      item = arr1[i];
    }
  }

  m = 0;
}

alert(item + " ( " + mf + " times ) ");

I've been checking out some similar questions on stackoverflow, just can't find the answers that I want.

我一直在查看有关 stackoverflow 的一些类似问题,只是找不到我想要的答案。

My questions are:

我的问题是:

  1. I don't understand why there needs to have two for loops.

  2. Why the need for mfand m. Seems a bit confusing.

  3. Is there other way of solution on this?

  1. 我不明白为什么需要有两个 for 循环。

  2. 为什么需要mfm。好像有点混乱。

  3. 对此有其他解决方法吗?

回答by Ajay Narain Mathur

User want's explanation of the code:

用户想要的代码解释:

Here they select the 1st element of the array and compare it with every element then on.

在这里,他们选择数组的第一个元素,然后将其与每个元素进行比较。

Then they increment the counter mevery time the same elements occur again, frequency of that element.

然后,m每次相同元素再次出现时,它们都会增加计数器,即该元素的频率。

Also a variable mfis kept to keep track of maximum frequency. Compare the elements frequency with maximum frequency and update itemand mfas per present element's frequency.

mf保留一个变量以跟踪最大频率。将元素频率与最大频率进行比较,itemmf根据当前元素的频率进行更新。

var arr1=[3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3]; //array
var mf = 1; //default maximum frequency
var m = 0;  //counter
var item;  //to store item with maximum frequency
for (var i=0; i<arr1.length; i++)    //select element (current element)
{
        for (var j=i; j<arr1.length; j++)   //loop through next elements in array to compare calculate frequency of current element
        {
                if (arr1[i] == arr1[j])    //see if element occurs again in the array
                 m++;   //increment counter if it does
                if (mf<m)   //compare current items frequency with maximum frequency
                {
                  mf=m;      //if m>mf store m in mf for upcoming elements
                  item = arr1[i];   // store the current element.
                }
        }
        m=0;   // make counter 0 for next element.
}

回答by Xotic750

I don't understand why there needs to have two for loops.

我不明白为什么需要有两个 for 循环。

There is no need for two loops, except for author choice.

除了作者选择之外,不需要两个循环。

Why the need for mfand m. Seems a bit confusing.

为什么需要mfm。好像有点混乱。

They are necessary for the solution that the author has chosen.

它们对于作者选择的解决方案是必要的。

mis the count of the current value being tested.

m是正在测试的当前值的计数。

mfis the current maximum frequency to test magainst and make a decision if the current element being tested is more frequent than the previously most frequent.

mf是当前要测试的最大频率,m并决定当前被测试的元素是否比以前最频繁的元素更频繁。

Is there other way of solution on this?

对此有其他解决方法吗?

Sure, plenty. Here is another one that takes things a step further.

当然,很多。这是另一个使事情更进一步的方法。

function getMostFrequentElement(inputArg) {
    var type = typeof inputArg,
        length,
        mostFrequent,
        counts,
        index,
        value;
    
    if (inputArg === null || type === 'undefined') {
        throw TypeError('inputArg was "null" or "undefined"');
    }

    mostFrequent = [];
    if (type === 'function' || !Object.prototype.hasOwnProperty.call(inputArg, 'length')) {
        mostFrequent[0] = inputArg;
        mostFrequent[1] = 1;
    } else {
        counts = {};
        length = inputArg.length;
        for (index = 0; index < length; index += 1) {
            value = inputArg[index];
            type = typeof value;
            counts[type] = counts[type] || {};
            counts[type][value] = (counts[type][value] || 0) + 1;
            if (!mostFrequent.length || counts[type][value] >= mostFrequent[1]) {
                mostFrequent[0] = value;
                mostFrequent[1] = counts[type][value];
            }
        }
    }

    return mostFrequent;
}

function logMostFrequentElement(inputArg) {
    var mostFrequentElement,
    element,
    text;

    try {
        mostFrequentElement = getMostFrequentElement(inputArg)
        if (mostFrequentElement.length) {
            element = mostFrequentElement[0];
            if (typeof element === 'string') {
                element = '"' + element + '"';
            }

            text = element + ' ( ' + mostFrequentElement[1] + ' times )';
        } else {
            text = 'No elements';
        }
    } catch (e) {
        text = e.message;
    }

    document.getElementById('out').appendChild(document.createTextNode(text + '\n'));
}

logMostFrequentElement();
logMostFrequentElement(1);
logMostFrequentElement(true);
logMostFrequentElement(function (x) { return x; });
logMostFrequentElement(/ab/g);
logMostFrequentElement([]);
logMostFrequentElement([1, 2]);
logMostFrequentElement([1, NaN, 2, NaN, 'NaN']);
logMostFrequentElement([1, Infinity, 2, Infinity, 'Infinity', -Infinity]);
logMostFrequentElement(['1', '2', 1, '2', 2]);
logMostFrequentElement([3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3]);
logMostFrequentElement([34, 'ab', 'ab', 'ab', 21, 34, 'ab', 34, 'ab', 21, 45, 99, 34]);
logMostFrequentElement('Also works with strings.');
<pre id="out"></pre>

回答by arnabkaycee

I really do not think there is a need for 2 loops in this solution. You can look at this prototyping code which uses a simple data structure called map:

我真的不认为在这个解决方案中需要 2 个循环。你可以看看这个原型代码,它使用了一个叫做 map 的简单数据结构:

var arr=[3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3];
var map = {};
var mostFrequentElement = arr[0];
function findMostFrequent(){
    for(var i = 0; i<arr.length; i++){
        if(!map[arr[i]]){
            map[arr[i]]=1;
        }else{
            ++map[arr[i]];
            if(map[arr[i]]>map[mostFrequentElement]){
                mostFrequentElement = arr[i];
            }
        }
    }
    alert(mostFrequentElement);
}

回答by Walter Chapilliquen - wZVanG

Using Array.prototype.reduce()and a temporary variable, You could do it this way (4 lines):

使用Array.prototype.reduce()和一个临时变量,你可以这样做(4 行):

var arr2 = [3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3];
var newArr = arr2.slice().sort(), most = [undefined, 0], counter = 0;

newArr.reduce(function(old, chr){
   old == chr ? ++counter > most[1] && (most = [chr, counter]) : (counter = 1)
   return chr
});

alert(most[0] + " ( "+most[1]+" times )");

ExplanationExcuse my english.

解释请原谅我的英语。

Using Array.prototype.reduce()can simplify your work. The following function first sorts their characters as 22333349aaaaa, then this counts your characters in sequence. I created a temp variable mostto store the data of the character most repeated.

使用Array.prototype.reduce()可以简化您的工作。以下函数首先将它们的字符排序为22333349aaaaa,然后按顺序计算您的字符。我创建了一个临时变量most来存储重复次数最多的字符的数据。

NoteThis only works for items of single digits.

Note这仅适用于个位数的项目。

回答by Walter Chapilliquen - wZVanG

This is an answer to point (3) using underscore:

这是使用下划线对第 (3) 点的回答:

function length(a) { return a.length; }

_.max(_.groupBy(arr1), length)[0]

How this works:

这是如何工作的:

> arr1 = [3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3];

> groups = _.groupBy(arr1)
< { 2: [2,2], 3: [3,3,3,3], 4: [4], 9: [9], a: ['a', 'a', ...] }

> max_group = _.max(groups, length)
< ['a', 'a', ...]

> max_group [0]
< 'a'

回答by RIYAJ KHAN

Please try this one.

请试试这个。

var mostFrequnet = null,mostFrequnetItem ;
var arr1 = [3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3];
arr1.sort();


for (var i=0;i<arr1.length;i++){ 

     var single = arr1[i]; 
     var total = (arr1.lastIndexOf(single)-arr1.indexOf(single))+1; 

     if(total > mostFrequnet) {

         mostFrequnetItem = arr1[i];
         mostFrequnet = total;
         i= arr1.lastIndexOf(single)+1;

    }
}

console.log(mostFrequnet);

console.log(mostFrequnetItem);

回答by Bibek Sharma

var nums = [3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3]; //array
var freqs = {};
var max_index;
var max_value = -1/0; // Negative infinity.

$.each(nums, function(i, v) {
  if (freqs[v] != undefined) {
  freqs[v]++;
} else {
    freqs[v] = 1;
}
});


$.each(freqs, function(num, freq) {
  if (freq > max_value) {
      max_value = freq;
      max_index = num;
    }
});

if(max_index != undefined) {
    alert("Most common element is " + max_index + " with " + max_value + "  repetition(s).");
}