Array Processing logic correction - javascript

I have an array [1,2,4,5,1,7,8,9,2,3]
and i would like it to generate all subset which sum of values are less than 10
current result [[1,2,4],[5,1],[7],[8],[9],[2,3]]
expected result [[4,5,1],[9,1],[8,2],[3,7],[1,2]]
that is what i did
var a = [1,2,4,5,1,7,8,9,2,3], tempArr = []; tempSum = 0, result = [];
for (var i = 0;i< a.length; i += 1 ) {
tempSum+=a[i];
tempArr.push(a[i]);
if((tempSum+a[i+1])>10) {
result.push(tempArr);
tempSum = 0;
tempArr = [];
} else if (i == a.length-1 && tempArr.length > 0) { // if array is [1,2,3]
result.push(tempArr);
}
}
but it gives me [[1,2,4],[5,1],[7],[8],[9],[2,3]] and it has 6 subset, but i expect to get [[4,5,1],[9,1],[8,2],[3,7],[1,2]] which has 5 subset.

Below logic is in JavaScript :-
var limit = 10;
var arr = [1,2,4,5,1,7,8,9,2,3];
arr.sort();
var ans = new Array ( );
while(arr.length >0){
var ts = arr[arr.length-1];
arr.splice(arr.length-1 , 1);
var ta= new Array ( );
ta.push(ts);
var x = arr.length-1;
while(x>=0){
if(ts + arr[x] <= limit){
ts = ts + arr[x];
ta.push(arr[x]);
arr.splice(x , 1);
}
x= x-1;
}
ans.push(JSON.stringify(ta));
}
alert(ans);
It is Giving Output as required .
[9,1],[8,2],[7,3],[5,4,1],[2]

I have removed duplicates then added maxSum parameter to combine function to generate all subset which have those conditions and then sorted subsets by sum of the values and sliced them.
You could change parameters to fit it for your problem.
var arr = [1,2,4,5,1,7,8,9,2,3]
MAX_SUM = 10,
MIN_SUBSET_LEN = 2,
RESULT_LEN = 5;
//remove duplicates
var uniqeSet = arr.filter(function(value, index){
return this.indexOf(value) == index
},arr);
// a function to get all subset which
// their length are greater than minLength and
// sum of values are little than maxSum
var combine = function(sourceArr, minLength, maxSum) {
var fn = function(n, src, got, all, sum) {
if(sum <= maxSum){
if (n == 0) {
if (got.length > 0) {
all.push({arr:got,sum:sum});
}
return;
}
for (var j = 0; j < src.length; j++) {
var tempSum = sum
fn(n - 1, src.slice(j + 1), got.concat([src[j]]), all, sum + src[j]);
}
}
return;
}
var all = [];
for (var i = minLength; i < sourceArr.length; i++) {
fn(i, sourceArr, [], all, 0);
}
return all;
}
var result = combine(uniqeSet, MIN_SUBSET_LEN, MAX_SUM);
var sortedSliced = result.sort(function(a1, a2){
return a2.sum - a1.sum;
}).slice(0, RESULT_LEN).map(function(m){return m.arr;});
console.log(JSON.stringify(sortedSliced));

Related

JavaScript Mini-Max Sum - Challenge from HackerRank website

Here is the Challenge:
https://www.hackerrank.com/challenges/mini-max-sum/problem
Despite my answer is returning the same number that matches the expected result, I have done something wrong because my answer has been rejected.
How can I solve it?
Here is the solution I had tried:
function miniMaxSum(arr) {
var arrClone1 = arr.slice()
var arrClone2 = arr.slice()
var arrMinor = arrClone1.sort(function(a, b){return a - b;})
arrMinor.pop()
var arrMajor = arrClone2.sort(function(a, b){return b - a;})
arrMajor.pop()
function getSum(a, b) {
return a + b;
}
var result1 = arrMinor.reduce(getSum)
var result2 = arrMajor.reduce(getSum)
console.log(`${result1} ${result2}`) // it is returning: 10 14
I think the solution should be easier:
function miniMaxSum(arr) {
let sum = arr.reduce((a, b) => a + b);
let maxVal = Math.max(...arr);
let minVal = Math.min(...arr);
console.log((sum - maxVal) + ' ' + (sum - minVal));
}
function miniMaxSum(arr) {
// Write your code here
let sum=arr.reduce((a,b)=>{
return a+b;
});
const min=sum-Math.max(...arr);
const max=sum-Math.min(...arr);
console.log(min+" "+max);
}
I found the answer. I noticed that it was mandatory to name the function argument as 'input' instead of 'arr'. That's why the answer was rejected by the HackerRank platform despite the code returned the right result in my editor, NOT in the HackerRank platform. If you do this simply adjustment, it works in the HackerRank platform too.
Just like that:
function miniMaxSum(input) { //'input' NOT 'arr'
var arrClone1 = input.slice() //'input' NOT 'arr'
var arrClone2 = input.slice() //'input' NOT 'arr'
//... rest of the code omitted
my solution:
let sumValue = arr.reduce((a, b) => {
return a + b;
});
const min = sumValue - Math.max(...arr);
const max = sumValue - Math.min(...arr);
const result = `${min} ${max}`
console.log(result);
Here's a more procedural solution to the problem.
function miniMaxSum(arr) {
let sum_min = 0
let sum_max = 0
let min_val = arr[0]
let max_val = arr[0]
let sum = 0
for(let index = 0; index < arr.length; index += 1){
if(arr[index] > max_val) {
max_val = arr[index]
}
if(arr[index] < min_val){
min_val = arr[index]
}
sum = sum + arr[index]
}
sum_min = sum - max_val
sum_max = sum - min_val
console.log(sum_min, sum_max)
}
This is my solution, I hope it works for you
function miniMaxSum(arr) {
// Write your code here
const max = arr.sort((a,b) => b-a).slice(0,4).reduce((a,b)=> a+b,0)
const min = arr.sort((a,b) => b-a).reverse().slice(0,4).reduce((a,b)=> a+b,0)
console.log(min,max)
}
You've got it right. The only "problem" is, that you're doing a Java or C++ coding challenge. (That's why they're mentioning the 32 bit integer).
The input shouldn't be an array but "A single line of five space-separated integers."
Here is another solution...
function miniMaxSum(arr) {
let minValue = 0, maxValue = 0, minIndex = 0, maxIndex = 0, minSum = 0, maxSum = 0;
minValue = Math.min(...arr);
maxValue = Math.max(...arr);
minIndex = arr.indexOf(minValue);
maxIndex = arr.indexOf(maxValue);
for (let i = 0; i < arr.length; i++){
if (minIndex != i) {
maxSum += arr[i];
}
if (maxIndex != i) {
minSum += arr[i];
}
}
console.log(minSum, maxSum);
}
miniMaxSum([1,2,3,4,5]);
Click Here to RUN
Using .reduce:
const arr = [1, 2, 3, 4, 5];
function miniMaxSum(arr) {
const res = arr.sort((a,b) => a-b).reduce((prev, cur, i) => {
if(i!=0) ( prev.max=prev.max+cur || cur);
if(i!=arr.length-1) ( prev.min=prev.min+cur || cur);
return prev;
}, [{max:0},{min:0}]);
console.log(res.min || 0, res.max || 0);
}
miniMaxSum(arr) // 10 14
Try this, it works for all cases:
function miniMaxSum(arr) {
let c = arr.sort();
let a = c.slice(0,4)
let b = c.slice(1,5)
console.log(a.reduce((p,n)=>p+n,0),b.reduce((p,n)=>p+n,0))
}
Another solution !
const numbers = arr.slice('').sort();
let min = 0;
let max = 0;
for (let i = 0; i < numbers.length; i++) {
if (i < 4) {
min = min + numbers[i];
}
if (i > 0 && i < 5) {
max += numbers[i];
}
}
console.log(`${min} ${max}`);
let numbers = arr.slice('').sort();
let maxScore = 0;
let minScore = 0;
for(let i = 0; i < numbers.length - 1; i++) {
minScore += numbers[i];
};
for(let j = 1; j < numbers.length; j++) {
maxScore += numbers[j];
};
console.log(`${minScore} ${maxScore}`);
function miniMaxSum(input) {
let minElem = 0, maxElem = 0, sum = 0;
minElem = input[0];
maxElem = minElem;
sum = minElem;
for (let i = 1; i < input.length; i++) {
sum += input[i];
if (input[i] < minElem) {
minElem = input[i];
}
if (input[i] > maxElem) {
maxElem = input[i];
}
}
let minresult = sum - maxElem;
let maxresult = sum - minElem;
console.log(minresult + " " + maxresult);
}
function miniMaxSum(arr) {
let sortarr = arr.sort();
let maxSum = 0;
let minSum = 0;
for (let i=0 ; i < arr.length - 1; i++ ){
minSum += sortarr[i];
}
for (let j=arr.length - 1; j > 0; j-- ){
maxSum += sortarr[j];
}
console.log(minSum + ' ' + maxSum);
}
guys. Just sharing my solution!
function miniMaxSum(input) {
input.sort((a,b) => a-b)
let min = 0, max = 0;
for(let i=0; i < input.length; i++)
{
min += input[i]
max += input[i]
}
console.log((min - input[input.length -1]) + ' ' + (max - input[0]))
}
Here is my solution --> This will handle duplicate and float values as well
Check the live demo below:
function miniMaxSum(arr) {
let tempArr=[];
var sum = arr.reduce((acc,cur)=>acc+cur);
arr.map((val)=>{
tempArr.push(Number(sum-val));
});
// unique values only
tempArr = [...new Set(tempArr)];
console.log(`${Math.min.apply(null,tempArr)} ${Math.max.apply(null,tempArr)}`);
}
miniMaxSum([7,69,2,203,894]);
this is my solution
function miniMaxSum(arr) {
// Write your code here
var sums = [];
for (var i=0; i<arr.length; i++) {
var num = arr.shift();
var sum = arr.reduce(function(acc, val) { return acc + val; }, 0);
sums.push(sum);
arr.push(num)
}
console.log(Math.min(...sums) + " " + Math.max(...sums));
}
function miniMaxSum(arr) {
let arrayMin = arr.slice() //new array for minimum
let arrayMax = arr.slice() //new array for maximum
let small = arrayMin.sort((a,b) => {return a - b}) //sort number small to big
let big = arrayMax.sort((a,b) => {return a - b}) //sort number small to big
function maxsum (a,b){return a + b} // that's function for calculate all numbers
let min = small.pop() //remove last element
let max = big.shift() //remove first element
let mins = arrayMin.reduce(maxsum) //apply maxsum function to array
let maxs = arrayMax.reduce(maxsum) //apply maxsum function to array
console.log(`${mins} ${maxs}`)
}
code worked for me is as below:
function miniMaxSum(arr) {
// Write your code here
let min = Math.min(...arr);
let max = Math.max(...arr);
let arrExceptMin, arrExceptMax;
let allEqual = arr.every(val => val === arr[0]);
if(allEqual) {
return console.log(sum(arr.slice(1)) + ' ' + sum(arr.slice(1)));
}
if(min) {
arrExceptMin = arr.filter(val => val !== min);
}
if(max) {
arrExceptMax = arr.filter(val => val !== max);
}
return console.log(sum(arrExceptMax) + ' ' + sum(arrExceptMin));
}
Simple Solution (I hope), there was not any problem with 'arr' argument with me.
function miniMaxSum(arr) {
// Write your code here
let a=0, b=0;
arr.sort();
for(let i=0; i<4; i++) {
a+=arr[i];
b+=arr[i+1];
}
console.log(a,b)
}
you can shorten the code
function miniMaxSum(arr) {
// Write your code here
arr.sort((a,b) => a-b)
let min= 0, max = 0;
for(let i = 0; i < arr.length-1 ; i++){
min += arr[i];
}
for(let j = 1; j < arr.length; j++){
max += arr[j];
}
console.log(min,max);
}
Here's a single loop variant.
function miniMaxSum(arr) {
let min = 0
let max = 0
let sum = 0
for (const n of arr) {
sum += n
if (!min || min > n) {
min = n
continue
}
if (max < n) {
max = n
}
}
console.log(sum - max, sum - min)
}
function miniMaxSum(arr) {
let arrMin = [].concat(arr).sort()
let arrMax = [].concat(arr).sort()
arrMin.pop();
arrMax.shift();
let arrMinReduced = arrMin.reduce((prev, curr) => prev + curr)
let arrMaxReduced = arrMax.reduce((prev, curr) => prev + curr)
console.log(arrMinReduced, arrMaxReduced)
}
miniMaxSum([1,2,3,4,5])
This solution uses only single loop and also no utility functions.
code is pretty much self-explanatory.
function miniMaxSum(arr) {
// Write your code here
const total = arr[0] + arr[1] + arr[2] + arr[3] + arr[4];
let max, min;
for (let i = 0; i < arr.length; i++) {
// Add all elements and subtract one element so that we sum of 4 items only
let sum = total - arr[i];
// Sets min & max both equal to sum on first iteration
if (max === undefined && min === undefined) {
max = sum;
min = sum; `enter code here`
} else if (max < sum) {
max = sum
} else if (min > sum) {
min = sum
}
}
console.log(min, max)
}
const arr = [1, 2, 3, 4, 5];
let len = arr.length;
let smallest = arr[0];
let largest = arr[0];
let minSum = 0;
let maxSum = 0;
function minMax(arr, len){
for(let i = 0; i<len; i++){
if(arr[i] >= largest){
largest = arr[i];
}
if(arr[i] <= smallest){
smallest = arr[i];
}
}
for(let i = 0; i < len; i++){
if(arr[i] > smallest){
maxSum += arr[i];
}
if(arr[i] < largest){
minSum += arr[i];
}
}
return console.log(minSum, maxSum)
}
minMax(arr, len)
solution in fewest possible lines, i think
'function miniMaxSum(arr) {
arr.sort((a,b)=>a-b);
let fSum=0, lSum=0;
for(let x=0; x<arr.length-1; x++){
fSum+=arr[x]
}
for(let x=1; x<arr.length; x++){
lSum+=arr[x]
}
console.log(fSum+" "+lSum);
}'

show most frequently occuring input value [duplicate]

var store = ['1','2','2','3','4'];
I want to find out that 2 appear the most in the array. How do I go about doing that?
I would do something like:
var store = ['1','2','2','3','4'];
var frequency = {}; // array of frequency.
var max = 0; // holds the max frequency.
var result; // holds the max frequency element.
for(var v in store) {
frequency[store[v]]=(frequency[store[v]] || 0)+1; // increment frequency.
if(frequency[store[v]] > max) { // is this frequency > max so far ?
max = frequency[store[v]]; // update max.
result = store[v]; // update result.
}
}
Solution with emphasis to Array.prototype.forEach and the problem of getting more than one key if the max count is shared among more items.
Edit: Proposal with one loop, only.
var store = ['1', '2', '2', '3', '4', '5', '5'],
distribution = {},
max = 0,
result = [];
store.forEach(function (a) {
distribution[a] = (distribution[a] || 0) + 1;
if (distribution[a] > max) {
max = distribution[a];
result = [a];
return;
}
if (distribution[a] === max) {
result.push(a);
}
});
console.log('max: ' + max);
console.log('key/s with max count: ' + JSON.stringify(result));
console.log(distribution);
arr.sort();
var max=0,result,freq = 0;
for(var i=0; i < arr.length; i++){
if(arr[i]===arr[i+1]){
freq++;
}
else {
freq=0;
}
if(freq>max){
result = arr[i];
max = freq;
}
}
return result;
Make a histogram, find the key for the maximum number in the histogram.
var hist = [];
for (var i = 0; i < store.length; i++) {
var n = store[i];
if (hist[n] === undefined) hist[n] = 0;
else hist[n]++;
}
var best_count = hist[store[0]];
var best = store[0];
for (var i = 0; i < store.length; i++) {
if (hist[store[i]] > best_count) {
best_count = hist[store[i]];
best = store[i];
}
}
alert(best + ' occurs the most at ' + best_count + ' occurrences');
This assumes either there are no ties, or you don't care which is selected.
Another ES6 option. Works with strings or numbers.
function mode(arr) {
const store = {}
arr.forEach((num) => store[num] ? store[num] += 1 : store[num] = 1)
return Object.keys(store).sort((a, b) => store[b] - store[a])[0]
}
If the array is sorted this should work:
function popular(array) {
if (array.length == 0) return [null, 0];
var n = max = 1, maxNum = array[0], pv, cv;
for(var i = 0; i < array.length; i++, pv = array[i-1], cv = array[i]) {
if (pv == cv) {
if (++n >= max) {
max = n; maxNum = cv;
}
} else n = 1;
}
return [maxNum, max];
};
popular([1,2,2,3,4,9,9,9,9,1,1])
[9, 4]
popular([1,2,2,3,4,9,9,9,9,1,1,10,10,10,10,10])
[10, 5]
This version will quit looking when the count exceeds the number of items not yet counted.
It works without sorting the array.
Array.prototype.most= function(){
var L= this.length, freq= [], unique= [],
tem, max= 1, index, count;
while(L>= max){
tem= this[--L];
if(unique.indexOf(tem)== -1){
unique.push(tem);
index= -1, count= 0;
while((index= this.indexOf(tem, index+1))!= -1){
++count;
}
if(count> max){
freq= [tem];
max= count;
}
else if(count== max) freq.push(tem);
}
}
return [freq, max];
}
//test
var A= ["apples","oranges","oranges","oranges","bananas",
"bananas","oranges","bananas"];
alert(A.most()) // [oranges,4]
A.push("bananas");
alert(A.most()) // [bananas,oranges,4]
I solved it this way for finding the most common integer
function mostCommon(arr) {
// finds the first most common integer, doesn't account for 2 equally common integers (a tie)
freq = [];
// set all frequency counts to 0
for(i = 0; i < arr[arr.length-1]; i++) {
freq[i] = 0;
}
// use index in freq to represent the number, and the value at the index represent the frequency count
for(i = 0; i < arr.length; i++) {
freq[arr[i]]++;
}
// find biggest number's index, that's the most frequent integer
mostCommon = freq[0];
for(i = 0; i < freq.length; i++) {
if(freq[i] > mostCommon) {
mostCommon = i;
}
}
return mostCommon;
}
This is my solution.
var max_frequent_elements = function(arr){
var a = [], b = [], prev;
arr.sort();
for ( var i = 0; i < arr.length; i++ ) {
if ( arr[i] !== prev ) {
a.push(arr[i]);
b.push(1);
} else {
b[b.length-1]++;
}
prev = arr[i];
}
var max = b[0]
for(var p=1;p<b.length;p++){
if(b[p]>max)max=b[p]
}
var indices = []
for(var q=0;q<a.length;q++){
if(b[q]==max){indices.push(a[q])}
}
return indices;
};
All the solutions above are iterative.
Here's a ES6 functional mutation-less version:
Array.prototype.mostRepresented = function() {
const indexedElements = this.reduce((result, element) => {
return result.map(el => {
return {
value: el.value,
count: el.count + (el.value === element ? 1 : 0),
};
}).concat(result.some(el => el.value === element) ? [] : {value: element, count: 1});
}, []);
return (indexedElements.slice(1).reduce(
(result, indexedElement) => (indexedElement.count > result.count ? indexedElement : result),
indexedElements[0]) || {}).value;
};
It could be optimized in specific situations where performance is the bottleneck, but it has a great advantage of working with any kind of array elements.
The last line could be replaced with:
return (indexedElements.maxBy(el => el.count) || {}).value;
With:
Array.prototype.maxBy = function(fn) {
return this.slice(1).reduce((result, element) => (fn(element) > fn(result) ? element : result), this[0]);
};
for clarity
If the array contains strings try this solution
function GetMaxFrequency (array) {
var store = array;
var frequency = []; // array of frequency.
var result; // holds the max frequency element.
for(var v in store) {
var target = store[v];
var numOccurences = $.grep(store, function (elem) {
return elem === target;
}).length;
frequency.push(numOccurences);
}
maxValue = Math.max.apply(this, frequency);
result = store[$.inArray(maxValue,frequency)];
return result;
}
var store = ['ff','cc','cc','ff','ff','ff','ff','ff','ff','yahya','yahya','cc','yahya'];
alert(GetMaxFrequency(store));
A fairly short solution.
function mostCommon(list) {
var keyCounts = {};
var topCount = 0;
var topKey = {};
list.forEach(function(item, val) {
keyCounts[item] = keyCounts[item] + 1 || 1;
if (keyCounts[item] > topCount) {
topKey = item;
topCount = keyCounts[item];
}
});
return topKey;
}
document.write(mostCommon(['AA', 'AA', 'AB', 'AC']))
This solution returns an array of the most appearing numbers in an array, in case multiple numbers appear at the "max" times.
function mode(numbers) {
var counterObj = {};
var max = 0;
var result = [];
for(let num in numbers) {
counterObj[numbers[num]] = (counterObj[numbers[num]] || 0) + 1;
if(counterObj[numbers[num]] >= max) {
max = counterObj[numbers[num]];
}
}
for (let num in counterObj) {
if(counterObj[num] == max) {
result.push(parseInt(num));
}
}
return result;
}

Return Sorted Array Without Modifying Original Array

I'm having trouble with a function returning the original array as opposed to the sorted array. I tried to slice the array and return the sorted but it is not working. Any ideas on how to fix this?
function sortArr( comparator, array ){
var newArray = array.slice();
for(var i = 0; i < newArray.size; i++)
{
var min = i;
for(var x = i; x < newArray.size; x++)
{
if(comparator(newArray[min],newArray[x]) == true)
{
min = x;
}
}
var temp = newArray[i];
newArray[i] = newArray[min];
newArray[min] = temp;
}
return newArray;
}
I fixed the function:
function sortArr( comparator, array ){
/*your code here*/
var i, x;
var min;
var newArray = array.slice();
for(i = 0; i < newArray.length - 1; i++)
{
min = i;
for(x = i + 1; x < newArray.length; x++)
{
if(comparator(newArray[min],newArray[x]) == true)
{
min = x;
}
}
if(min != i){
var temp = newArray[i];
newArray[i] = newArray[min];
newArray[min] = temp;
}
}
return newArray;
}
Copy the array with slice and then use native sort:
function sortArr(comparator, array) {
return array.slice().sort(function(a,b) {
return comparator(a,b) * 2 - 1;
});
}
Your sorting algorithm doesn't look quite right. For a start the swapping of values should be inside the if statement. I would also advise to look at #Oriol's solution which is far more elegant.
function sortArr( comparator, array ){
var newArray = array.slice();
for(var i = 0; i < newArray.size; i++)
{
var min = i;
for(var x = i; x < newArray.size; x++)
{
if(comparator(newArray[min],newArray[x]) == true)
{
var temp = newArray[i];
newArray[i] = newArray[min];
newArray[min] = temp;
min = x;
}
}
}
return newArray;
}
{"index.js":"var globalArray = [5, 6, 3, 2, 9];
function nonMutatingSort(arr) {
let newArr = globalArray.slice();\n let emptyArr = [];
return emptyArr.concat(newArr).sort();
}
nonMutatingSort(globalArray);"}

Prime numbers not printing in Javascript

I have the following code to find the prime numbers from 2 to 1000:
#!/usr/bin/env node
var primesarray = function(n) {
var nums = [];
for (var i = 0; i < n; i++) {
nums.push("1");
}
return nums;
};
var primes = function(arr) {
var i = 2;
var primes = [];
for (i = 2; i < arr.length - 1; i++) {
if (arr[i] === "1")
primes.push(i);
for (j = 2; Math.pow(i, j) < arr.length - 1; j++ ) {
arr[Math.pow(i,j)] = "0";
}
}
return primes;
};
// Print to console
var fmt = function(arr) {
return arr.join(",");
};
var k = 1000;
console.log("primes(" + k + ")");
console.log(fmt(primes(k)));
When I run the file, it just prints the first console.log line. I'm not seeing what's wrong here.
The function primes is written to expect an array, but you're passing it an integer.
Did you mean fmt(primes(primesarray(k)))?
(That does at least print a list of numbers, but I'm afraid many of them are not primes!)
You need to prime you array ;)
var arr = primesarray(k)
like this
var k = 1000;
var arr = primesarray(k)
console.log(primes(arr));
console.log(fmt(primes(arr)));
DEMO
Some actual solutions: http://www.codecademy.com/forum_questions/5033d10f77955e0002004142

Get the item that appears the most times in an array

var store = ['1','2','2','3','4'];
I want to find out that 2 appear the most in the array. How do I go about doing that?
I would do something like:
var store = ['1','2','2','3','4'];
var frequency = {}; // array of frequency.
var max = 0; // holds the max frequency.
var result; // holds the max frequency element.
for(var v in store) {
frequency[store[v]]=(frequency[store[v]] || 0)+1; // increment frequency.
if(frequency[store[v]] > max) { // is this frequency > max so far ?
max = frequency[store[v]]; // update max.
result = store[v]; // update result.
}
}
Solution with emphasis to Array.prototype.forEach and the problem of getting more than one key if the max count is shared among more items.
Edit: Proposal with one loop, only.
var store = ['1', '2', '2', '3', '4', '5', '5'],
distribution = {},
max = 0,
result = [];
store.forEach(function (a) {
distribution[a] = (distribution[a] || 0) + 1;
if (distribution[a] > max) {
max = distribution[a];
result = [a];
return;
}
if (distribution[a] === max) {
result.push(a);
}
});
console.log('max: ' + max);
console.log('key/s with max count: ' + JSON.stringify(result));
console.log(distribution);
arr.sort();
var max=0,result,freq = 0;
for(var i=0; i < arr.length; i++){
if(arr[i]===arr[i+1]){
freq++;
}
else {
freq=0;
}
if(freq>max){
result = arr[i];
max = freq;
}
}
return result;
Make a histogram, find the key for the maximum number in the histogram.
var hist = [];
for (var i = 0; i < store.length; i++) {
var n = store[i];
if (hist[n] === undefined) hist[n] = 0;
else hist[n]++;
}
var best_count = hist[store[0]];
var best = store[0];
for (var i = 0; i < store.length; i++) {
if (hist[store[i]] > best_count) {
best_count = hist[store[i]];
best = store[i];
}
}
alert(best + ' occurs the most at ' + best_count + ' occurrences');
This assumes either there are no ties, or you don't care which is selected.
Another ES6 option. Works with strings or numbers.
function mode(arr) {
const store = {}
arr.forEach((num) => store[num] ? store[num] += 1 : store[num] = 1)
return Object.keys(store).sort((a, b) => store[b] - store[a])[0]
}
If the array is sorted this should work:
function popular(array) {
if (array.length == 0) return [null, 0];
var n = max = 1, maxNum = array[0], pv, cv;
for(var i = 0; i < array.length; i++, pv = array[i-1], cv = array[i]) {
if (pv == cv) {
if (++n >= max) {
max = n; maxNum = cv;
}
} else n = 1;
}
return [maxNum, max];
};
popular([1,2,2,3,4,9,9,9,9,1,1])
[9, 4]
popular([1,2,2,3,4,9,9,9,9,1,1,10,10,10,10,10])
[10, 5]
This version will quit looking when the count exceeds the number of items not yet counted.
It works without sorting the array.
Array.prototype.most= function(){
var L= this.length, freq= [], unique= [],
tem, max= 1, index, count;
while(L>= max){
tem= this[--L];
if(unique.indexOf(tem)== -1){
unique.push(tem);
index= -1, count= 0;
while((index= this.indexOf(tem, index+1))!= -1){
++count;
}
if(count> max){
freq= [tem];
max= count;
}
else if(count== max) freq.push(tem);
}
}
return [freq, max];
}
//test
var A= ["apples","oranges","oranges","oranges","bananas",
"bananas","oranges","bananas"];
alert(A.most()) // [oranges,4]
A.push("bananas");
alert(A.most()) // [bananas,oranges,4]
I solved it this way for finding the most common integer
function mostCommon(arr) {
// finds the first most common integer, doesn't account for 2 equally common integers (a tie)
freq = [];
// set all frequency counts to 0
for(i = 0; i < arr[arr.length-1]; i++) {
freq[i] = 0;
}
// use index in freq to represent the number, and the value at the index represent the frequency count
for(i = 0; i < arr.length; i++) {
freq[arr[i]]++;
}
// find biggest number's index, that's the most frequent integer
mostCommon = freq[0];
for(i = 0; i < freq.length; i++) {
if(freq[i] > mostCommon) {
mostCommon = i;
}
}
return mostCommon;
}
This is my solution.
var max_frequent_elements = function(arr){
var a = [], b = [], prev;
arr.sort();
for ( var i = 0; i < arr.length; i++ ) {
if ( arr[i] !== prev ) {
a.push(arr[i]);
b.push(1);
} else {
b[b.length-1]++;
}
prev = arr[i];
}
var max = b[0]
for(var p=1;p<b.length;p++){
if(b[p]>max)max=b[p]
}
var indices = []
for(var q=0;q<a.length;q++){
if(b[q]==max){indices.push(a[q])}
}
return indices;
};
All the solutions above are iterative.
Here's a ES6 functional mutation-less version:
Array.prototype.mostRepresented = function() {
const indexedElements = this.reduce((result, element) => {
return result.map(el => {
return {
value: el.value,
count: el.count + (el.value === element ? 1 : 0),
};
}).concat(result.some(el => el.value === element) ? [] : {value: element, count: 1});
}, []);
return (indexedElements.slice(1).reduce(
(result, indexedElement) => (indexedElement.count > result.count ? indexedElement : result),
indexedElements[0]) || {}).value;
};
It could be optimized in specific situations where performance is the bottleneck, but it has a great advantage of working with any kind of array elements.
The last line could be replaced with:
return (indexedElements.maxBy(el => el.count) || {}).value;
With:
Array.prototype.maxBy = function(fn) {
return this.slice(1).reduce((result, element) => (fn(element) > fn(result) ? element : result), this[0]);
};
for clarity
If the array contains strings try this solution
function GetMaxFrequency (array) {
var store = array;
var frequency = []; // array of frequency.
var result; // holds the max frequency element.
for(var v in store) {
var target = store[v];
var numOccurences = $.grep(store, function (elem) {
return elem === target;
}).length;
frequency.push(numOccurences);
}
maxValue = Math.max.apply(this, frequency);
result = store[$.inArray(maxValue,frequency)];
return result;
}
var store = ['ff','cc','cc','ff','ff','ff','ff','ff','ff','yahya','yahya','cc','yahya'];
alert(GetMaxFrequency(store));
A fairly short solution.
function mostCommon(list) {
var keyCounts = {};
var topCount = 0;
var topKey = {};
list.forEach(function(item, val) {
keyCounts[item] = keyCounts[item] + 1 || 1;
if (keyCounts[item] > topCount) {
topKey = item;
topCount = keyCounts[item];
}
});
return topKey;
}
document.write(mostCommon(['AA', 'AA', 'AB', 'AC']))
This solution returns an array of the most appearing numbers in an array, in case multiple numbers appear at the "max" times.
function mode(numbers) {
var counterObj = {};
var max = 0;
var result = [];
for(let num in numbers) {
counterObj[numbers[num]] = (counterObj[numbers[num]] || 0) + 1;
if(counterObj[numbers[num]] >= max) {
max = counterObj[numbers[num]];
}
}
for (let num in counterObj) {
if(counterObj[num] == max) {
result.push(parseInt(num));
}
}
return result;
}

Categories