最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Find the most frequent item of an array (not just strings) - Stack Overflow

programmeradmin2浏览0评论

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

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 ) ");

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

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.

My questions are:

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

  2. Why the need for mf and m. Seems a bit confusing.

  3. Is there other way of solution on this?

Share Improve this question edited Jul 5, 2015 at 12:38 chichi asked Jul 5, 2015 at 6:22 chichichichi 691 gold badge1 silver badge5 bronze badges 4
  • 1 possible duplicate of Get the element with the highest occurrence in an array – Tushar Commented Jul 5, 2015 at 6:26
  • 1 You really should include the code you are asking about in your question - that is the policy here at StackOverflow as external links tend to disappear or change over time rendering some questions useless in the future because the full context of what was asked is no longer available. – jfriend00 Commented Jul 5, 2015 at 6:55
  • It is not a question of javascript, it is a question of the theory of algorithms. If you are interested in a deeper understanding, you should look for online courses of the theory of algorithms (Coursera?) or lectures (Stanford?). – stdob-- Commented Jul 5, 2015 at 6:57
  • In case you're still looking for an answer! stackoverflow.com/questions/40410470/… – daanvanham Commented Nov 4, 2016 at 11:08
Add a comment  | 

8 Answers 8

Reset to default 4

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:

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);
}

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 m every time the same elements occur again, frequency of that element.

Also a variable mf is kept to keep track of maximum frequency. Compare the elements frequency with maximum frequency and update item and mf as per present element's frequency.

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.
}

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

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

Why the need for mf and m. Seems a bit confusing.

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

m is the count of the current value being tested.

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

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>

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

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 )");

Explanation Excuse 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 most to store the data of the character most repeated.

Note This only works for items of single digits.

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

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'
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).");
}

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);

mf is the global count for number thats with highest frequency and m is the local count inisde loop

发布评论

评论列表(0)

  1. 暂无评论