3

In my task I have to write a program that finds the most frequent number in an array and how many time it is repeated. I wrote something, but only prints the max number of repeating time. So my question is how can I print the value of this element(max number)(in my case is 4)? :)

var array = ['13', '4', '1', '1', '4', '2', '3', '4', '4', '1', '2', '4', '9', '3'];

function frequentNumber(arr) {
   var result = [],
       result2 = [];

   sorted_arr = arr.sort();

    console.log(sorted_arr);
    n=1;
    buffer = [];

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

        if (sorted_arr[i + 1] === sorted_arr[i]) {
            n++;
        }else{

            if(buffer.length != 0 ){
                for(var j = 0; j < buffer.length; j++){

                    if(buffer[j] < n){
                        result = sorted_arr[j] + " is " + n;
                    }
                }
            }else{buffer.push(n)}

            n=1;
        }
    }

//    console.log(Math.max.apply(Math, buffer));
    console.log(buffer);
}

frequentNumber(array); 
Santiya
  • 195
  • 3
  • 12
  • 1
    Possible duplicate of [Get the element with the highest occurrence in an array](http://stackoverflow.com/questions/1053843/get-the-element-with-the-highest-occurrence-in-an-array) – krassdanke Aug 22 '16 at 14:57
  • Add a variable that holds the current highest counted number and print it out in the end. Override it whenever you found a number which you counted more often than the previous one. – Danmoreng Aug 22 '16 at 14:58
  • what should happen, if you have two values with the same count? – Nina Scholz Aug 22 '16 at 15:02

7 Answers7

4

You can use .reduce to create an object with the numbers and the times they're listed - then simply iterate the object and find the highest value:

var ranks = array.reduce(function(totals, num) {
    if (!totals[num]) totals[num] = 0;
    totals[num]++;

    return totals;
}, {});

//Iterate and find
var max = 0;
Object.keys(ranks).forEach(function(num) {
    if (ranks[num] > max) {
        max = num;
    }
});

console.log(max); //4 - number
console.log(ranks[max]); //5 - times repeated

This doesn't take numbers with the same count into play - whichever number is iterated in the object first with the highest count will be the result - and since objects are unordered, a same count could have different results over multiple executions.

tymeJV
  • 103,943
  • 14
  • 161
  • 157
1

The easiest, and properbly most correct method, is to use the native Array.Sort method.

Inside the loop, simply count the frequency of each number, compare and return.

var arr = ['13', '4', '1', '1', '4', '2', '3', '4', '4', '1', '2', '4', '9', '3'];

function sortByOccurence(arr) {
  return arr.sort(function(a, b) {
    var A = 0,
      B = 0;
    if (a === b) {
      return 0;
    }
    for (var i = 0; i < arr.length; i++) {
      if (arr[i] == a) {
        A++;
      }
      if (arr[i] == b) {
        B++;
      }
    }
    return B - A;
  });
}
console.log(sortByOccurence(arr));
Emil S. Jørgensen
  • 6,216
  • 1
  • 15
  • 28
  • 2
    IMO doing someone's homework for them is counter-productive. Doing it without even bothering to explain anything is even worse. – Dave Newton Aug 22 '16 at 14:59
  • "most correct" - makes no sense. something is either correct or not. – Karoly Horvath Aug 22 '16 at 15:05
  • @DaveNewton accidently hit post before i was done. And i didn't solve it, i just sorted it. @Karoly Horvath, there are many ways to go about this, like `Array.reduce`, `Array.Map` or any number of custom sorting functions that basically reinvents the `Array.Sort` functionality so there is more than one correct. This method is standards compliant, which is why i would call it the correct method. – Emil S. Jørgensen Aug 22 '16 at 15:12
  • This answer is probably the best. Not sure why all the negativity in comments. – WinEunuuchs2Unix Jan 31 '22 at 00:43
1

I use Underscore library:

  var found = _.chain(array).countBy().pairs().max(_.last);

  var valueOfFrequent = found.head().value();
  var numberOfFrequent = found.tail().value();

  alert("number '" + valueOfFrequent + "' time of frequent: " + numberOfFrequent );

Try code in jsfiddle

Mohammad Akbari
  • 4,486
  • 6
  • 43
  • 74
0

This is a task so I'd rather not give you the answers but a possible solution could be something like this.

  1. Instantiate an object with keys as the numbers in your array and the values as the number of repetitions in your array. All initial counts should be 0 and you increase it by 1 as you see each number.

ie. count['4'] = 4 in the end.

  1. Find the max value and save the key when you loop through the object.

This is not the most optimal but I'm sure it will do fine in your task and will be the easiest to follow. First loop does the counting. Second loop finds the maximum repeats.

Jeff
  • 650
  • 5
  • 16
0

You would need create a variable that keeps the current highest counted value and override it when you found a more often counted value.

Here is a pretty simple algorithm for that task.

function getMostPopularElement(givenArray){
  var count = 1, tempCount, tempPopular;
  var popular = givenArray[0];
  for (var i = 0; i < givenArray.length - 1; i++){
    tempPopular = givenArray[i];
    tempCount = 0;
    for (var j = 1; j < givenArray.length; j++){
      if (tempPopular === givenArray[j])
        tempCount++;
    }
    if (tempCount > count){
      popular = tempPopular;
      count = tempCount;
    }
  }
  return popular;
}

Please make sure that if two or more values equally encountered in the array, so the function below returns the first encountered value. It based on this tempCount > count comparison. If you change it on tempCount >= count, so the most popular value would be the last encoutered one.

Artyom Pranovich
  • 6,814
  • 8
  • 41
  • 60
0

You could use a hash table for count and the get the max count value of it in a single loop with Array#reduce.

The result of max is an array, because the original array could contain values with the same count.

var array = ['13', '4', '1', '1', '4', '2', '3', '4', '4', '1', '2', '4', '9', '3'],
    count = Object.create(null),
    max = array.reduce(function (r, a, i) {
        count[a] = (count[a] || 0) + 1;
        if (!i || count[a] > count[r[0]]) {
            return [a];
        }
        if (a !== r[0] && count[a] === count[r[0]]) {
            r.push(a);
        }
        return r;
    }, undefined);

console.log(max);
console.log(count);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

I think my usage of variable names will help make it more clear without too much commenting.

var array = ['13', '4', '1', '1', '4', '2', '3', '4', '4', '1', '2', '4', '9', '3'];
var mostUsed;
var currentNumber;
var lastNumber;    
var currentCount;
var lastCount;
function frequentNumber(arr) {
array.sort();  
var y = 1;
var tempArr = [];     
    for (x = 0; x < array.length; x++){
        if(array[x] == array[y]){
            tempArr.push(array[x]);
            currentNumber = array[x];
        }
        else{
            tempArr.push(array[x]);
            currentNumber = array[x];
            currentCount = tempArr.length;
            //console.log(currentNumber +' occurs ' + currentCount + ' times');
            tempArr =[];
            if (lastCount >= currentCount){
                mostUsed = lastNumber;
            }
            else{
                mostUsed = currentNumber
            }
            lastCount = currentCount;
            lastNumber = currentNumber;


        }


       y++;   
    }
    console.log('Most Used Number is = ' +mostUsed);
}   
frequentNumber(array);  

What ends up happening is that after sorting your array you check if the first spot (0) matches the second spot (1) if it does you push it into a temporary array that you are just using for counting purposes. When you finally reach an item that doesn't match it still pushes it into the array but then gets the total length of that array and stores it as the currentCount and the number that is in use as the currentNumber.

Another conditional is then run on those variables. On the first iteration of all the loops there is nothing to check against since the are currentNumber is the most used number because it's compared to nothing. So that first number is tucked into what we will be using as the mostUsed variable. After that we store the current data into these other variables called lastNumber and lastCount. Then on each loop after this you compare the current count to the last count. If the lastCount is higher it stores that lastNumber as the most used and doesn't change anything. However if the currentNumber is higher it will store that as the most used number.

Does this make sense? If you don't follow the logic you should add comments at various points in the code so that you better understand it. This was a well though out and interesting coding test by your teacher. I enjoyed working through it in the cleanest simplest way.

D. Cantatore
  • 187
  • 12