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:
I don't understand why there needs to have two for loops.
Why the need for
mf
andm
. Seems a bit confusing.Is there other way of solution on this?
- 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
8 Answers
Reset to default 4I 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
andm
. 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