Find the most commonly used array element (not just strings)

Can someone get me through exercise ? Write a JavaScript program to find the most commonly used array element.

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 was looking through some similar questions in stackoverflow, just can't find the answers I want.

My questions:

  • I do not understand why there should be two for loops.

  • Why mf and m needed. It seems a bit confusing.

  • Is there any other solution?

+3
javascript arrays algorithm
Jul 05 '15 at 6:22
source share
7 answers

The user wants to explain the code:

Here they select the 1st element of the array and compare it with each element and beyond.

Then they increase the counter m each time the same elements are repeated, the frequency of this element.

The mf variable is also supported to track the maximum frequency. Compare the frequency of the elements with the maximum frequency and update item and mf according to the current frequency of the element.

 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. } 
+2
Jul 05 '15 at 6:35
source share

I do not understand why you need to have two cycles.

There is no need for two cycles, except for the choice of the author.

Why mf and m are needed. It seems a bit confusing.

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

m is the countdown of the current test value.

mf is the current maximum frequency for testing m against and deciding if the current item being tested is more frequent than the previous most frequent.

Is there any other solution?

Of course, a lot. Here is another step that takes 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> 
+2
Jul 05 '15 at 11:21
source share

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

 function length(a) { return a.length; } _.max(_.groupBy(arr1), length)[0] 

How it 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' 
+1
Jul 05 '15 at 9:49
source share
 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)."); } 
0
Jul 05 '15 at 7:32
source share

I really don't think that 2 cycles are required in this solution. You can see this prototyping code that 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); } 
0
Jul 05 '15 at 7:46
source share

Using Array.prototype.reduce () and a temporary variable, you can 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 Sorry my English.

Using Array.prototype.reduce () can simplify your work. The following function first sorts its characters as 22333349aaaaa , and then counts your characters in sequence. I created a temporary variable most to store the data of the character itself.

Note This only works for elements with single digits.

0
Jul 05 '15 at 9:09
source share

Try this option.

 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); 
0
Jul 05 '15 at 10:23
source share



All Articles