how to get mode in array - javascript

I have wounder`d for a while about how to get mode in array. That elements that are the same in array would be put together.
For ex. [Alex, Steven, Georg, Alice, Alex, Georg];
return would be: Alex: 2, Steven: 1, Georg: 2, Alice:1;
I wrote the code but it works only for numbers from 1 to 10. And for sure there is a better way.
(I don`t think you need my code but will paste it anyway.)
var mode = function (data){
var result1 = data.filter(function (verde) {return verde === 1});
var result2 = data.filter(function (verde) {return verde === 2});
var result3 = data.filter(function (verde) {return verde === 3});
var result4 = data.filter(function (verde) {return verde === 4});
var result5 = data.filter(function (verde) {return verde === 5});
var result6 = data.filter(function (verde) {return verde === 6});
var result7 = data.filter(function (verde) {return verde === 7});
var result8 = data.filter(function (verde) {return verde === 8});
var result9 = data.filter(function (verde) {return verde === 9});
var nyadata = [result1.length, result2.length,
result3.length, result4.length,
result5.length, result6.length,
result7.length, result8.length,
result9.length];
var nyarreymax = Math.max.apply(Math, nyadata);
if (nyarreymax === result1.length){return 1;}
if (nyarreymax === result2.length){return 2;}
if (nyarreymax === result3.length){return 3;}
if (nyarreymax === result4.length){return 4;}
if (nyarreymax === result5.length){return 5;}
if (nyarreymax === result6.length){return 6;}
if (nyarreymax === result7.length){return 7;}
if (nyarreymax === result8.length){return 8;}
if (nyarreymax === result9.length){return 9;}
else { return false;}
Hope you can help me to know code that works generally for strings and all integers.

I'm a beginner at js myself and was looking for this same solution not long ago. Here's one I found that should be what you're looking for:
function findMode(arr) {
var map = {};
for (var i = 0; i < arr.length; i++) {
if (map[arr[i]] === undefined) {
map[arr[i]] = 0;
}
map[arr[i]] += 1;
}
var greatestFreq = 0;
var mode;
for (var prop in map) {
if (map[prop] > greatestFreq) {
greatestFreq = map[prop];
mode = prop;
}
}
return mode;
}

You can try this using reduce() , see your console that shows value with counts.
Demo http://jsfiddle.net/ak69f/
var array_elements = ['Alex', 'Steven', 'Georg', 'Alice', 'Alex', 'Georg'];
var result = array_elements.reduce(function(p, c){
if (c in p) {
p[c]++;
} else {
p[c]=1;
}
return p;
}, []);
console.log(result);

Here's a simple recursive solution, which seems to be the fastest of the four answers as you can see here: http://jsperf.com/array-mode.
var a = ["Alex", "Steven", "Georg", "Alice", "Alex", "Georg"];
function getMode(a, result) {
result = result || {};
if (a.length === 0){
return result;
}
var head = a.shift();
if (result[head]){
result[head]++;
}
else{
result[head] = 1;
}
return getMode(a, result);
}
console.log(getMode(a));

First, define a new array that will hold your results.
Iterate through your names array. Inside of each loop, iterate through the results array. If the current name in your names array exists within the results array, change the value.
For example, if your names array is on the second "Alex", and you iterate through the results array and find that "Alex:1" already exists, change the value to "Alex:2" (you will have to do a little bit of string parsing for that).
If the name does not exist already, add it to the end as ":1"
Then if you want to return the mode, you will have to write another loop that finds the maximum occurrence. Have a variable that keeps track of the array position of the name with the highest number (let's say it's called maxIndex). For each item in the array, compare it to the value of the array at maxIndex. If it's higher, reset maxIndex to the current index. If it's equal to or less than, move onto the next item of the array.
I know that was very wordy, so let me know if you have any questions.

An alternative approach to this is to create a function that takes in your array, assigns each unique array value to an object property and if it already exists, increase the object properties value by one, like so;
function countArray(array){
var results = {};
for(var x = 0; x < array.length; x++){
if(results[array[x]] == undefined){
results[array[x]] = 1;
}else{
results[array[x]] += 1;
}
}
return results;
}
var checkArray = countArray(['alex', 'george', 'steve', 'alex']);
console.log(checkArray);
// outputs "Object {alex: 2, george: 1, steve: 1}"
Then you could access the results as needed by calling
console.log(checkArray.alex); // outputs 2

var numbers = [1,2,2,3,4,5];
var counts = numbers.reduce((counts, e) => { counts[e] = counts[e] ? counts[e] + 1 : 1; return counts; }, {});
var mode = Object.keys(counts).reduce((a, b) => (counts[a] > counts[b] ? a : b ));
console.log(mode);
Reduce function can help a lot in aggregations.

The way I have found is very similar to the accepted answer however I thought I would add that if no items repeat, or no single item repeats the most, there is no mode, so my function checks that and returns null if that's the case.
function calcMode(data) {
let counts = {};
data.forEach((d) => {
if (counts[d] === undefined) {
counts[d] = 0;
}
counts[d] += 1;
});
let mode,
max = 0,
repeats = 0;
Object.keys(counts).forEach((k) => {
if (counts[k] > max) {
max = counts[k];
mode = k;
repeats = 0;
} else if (counts[k] == max) repeats += 1;
});
if (!repeats) {
if (isNaN(mode)) return mode;
else return +mode;
} else return null;
}

This was my approach, I tried a "functional" style using reduce. It also supports multimodes, so it will return an array of modes.
export function mode(vector) {
if (vector.length === 0) return undefined
return (vector.reduce((accu, curr) => {
const freqsMap = accu.freqsMap
freqsMap.set(curr, (freqsMap.get(curr) || 0) + 1)
const maxCount = freqsMap.get(curr) > accu.maxCount
? freqsMap.get(curr)
: accu.maxCount
const modes = freqsMap.get(curr) === accu.maxCount
? [...accu.modes, curr]
: freqsMap.get(curr) > accu.maxCount
? [curr]
: accu.modes
return { freqsMap, maxCount, modes }
}, { freqsMap: new Map(), maxCount: 1, modes: []})).modes
}

Related

How to remove same value if it has in an array? [duplicate]

Let's assume that I have ;
var array = [1,2,3,4,4,5,5];
I want it to be;
var newArray = [1,2,3];
I want to remove the duplicates completely rather than keeping them as unique values. Is there a way achieve that through reduce method ?
You could use Array#filter with Array#indexOf and Array#lastIndexOf and return only the values which share the same index.
var array = [1, 2, 3, 4, 4, 5, 5],
result = array.filter(function (v, _, a) {
return a.indexOf(v) === a.lastIndexOf(v);
});
console.log(result);
Another approach by taking a Map and set the value to false, if a key has been seen before. Then filter the array by taking the value of the map.
var array = [1, 2, 3, 4, 4, 5, 5],
result = array.filter(
Map.prototype.get,
array.reduce((m, v) => m.set(v, !m.has(v)), new Map)
);
console.log(result);
I guess it won't have some remarkable performance, but I like the idea.
var array = [1,2,3,4,4,5,5],
res = array.reduce(function(s,a) {
if (array.filter(v => v !== a).length == array.length-1) {
s.push(a);
}
return s;
}, []);
console.log(res);
Another option is to use an object to track how many times an element is used. This will destroy the array order, but it should be much faster on very large arrays.
function nukeDuplications(arr) {
const hash = {};
arr.forEach(el => {
const qty = hash[el] || 0;
hash[el] = qty+1;
});
const ret = [];
Object.keys(hash).forEach(key => {
if (hash[key] === 1) {
ret.push(Number(key));
}
})
return ret;
}
var array = [1,2,3,4,4,5,5];
console.log(nukeDuplications(array));
A slightly more efficient solution would be to loop over the array 1 time and count the number of occurrences in each value and store them in an object using .reduce() and then loop over the array again with .filter() to only return items that occurred 1 time.
This method will also preserve the order of the array, as it merely uses the object keys as references - it does not iterate over them.
var array = [1,2,3,4,4,5,5];
var valueCounts = array.reduce((result, item) => {
if (!result[item]) {
result[item] = 0;
}
result[item]++;
return result;
}, {});
var unique = array.filter(function (elem) {
return !valueCounts[elem] || valueCounts[elem] <= 1;
});
console.log(unique)
Another option is to use an object to track how many times an element is used. This will destroy the array order, but it should be much faster on very large arrays.
// Both versions destroy array order.
// ES6 version
function nukeDuplications(arr) {
"use strict";
const hash = {};
arr.forEach(el => {
const qty = hash[el] || 0;
hash[el] = qty + 1;
});
const ret = [];
Object.keys(hash).forEach(key => {
if (hash[key] === 1) {
ret.push(Number(key));
}
})
return ret;
}
// ES5 version
function nukeDuplicationsEs5(arr) {
"use strict";
var hash = {};
for (var i = 0; i < arr.length; i++) {
var el = arr[i];
var qty = hash[el] || 0;
hash[el] = qty + 1;
};
var ret = [];
for (let key in hash) {
if (hash.hasOwnProperty(key)) {
if (hash[key] === 1) {
ret.push(Number(key));
}
}
}
return ret;
}
var array = [1, 2, 3, 4, 4, 5, 5];
console.log(nukeDuplications(array));
console.log(nukeDuplicationsEs5(array));
There are a lot of over-complicated, and slow running code here. Here's my solution:
let numbers = [1,2,3,4,4,4,4,5,5]
let filtered = []
numbers.map((n) => {
if(numbers.indexOf(n) === numbers.lastIndexOf(n)) // If only 1 instance of n
filtered.push(n)
})
console.log(filtered)
you can use this function:
function isUniqueInArray(array, value) {
let counter = 0;
for (let index = 0; index < array.length; index++) {
if (array[index] === value) {
counter++;
}
}
if (counter === 0) {
return null;
}
return counter === 1 ? true : false;
}
const array = [1,2,3,4,4,5,5];
let uniqueValues = [];
array.forEach(element => {
if(isUniqueInArray(array ,element)){
uniqueValues.push(element);
}
});
console.log(`the unique values is ${uniqueValues}`);
If its help you, you can install the isUniqueInArray function from my package https://www.npmjs.com/package/jotils or directly from bit https://bit.dev/joshk/jotils/is-unique-in-array.
My answer is used map and filter as below:
x = [1,2,3,4,2,3]
x.map(d => x.filter(i => i == d).length < 2 ? d : null).filter(d => d != null)
// [1, 4]
Object.values is supported since ES2017 (Needless to say - not on IE).
The accumulator is an object for which each key is a value, so duplicates are removed as they override the same key.
However, this solution can be risky with misbehaving values (null, undefined etc.), but maybe useful for real life scenarios.
let NukeDeps = (arr) => {
return Object.values(arr.reduce((curr, i) => {
curr[i] = i;
return curr;
}, {}))
}
I would like to answer my questions with an answer I came up with upon reading it again
const array = [1, 2, 3, 4, 4, 5, 5];
const filtered = array.filter(item => {
const { length } = array.filter(currentItem => currentItem === item)
if (length === 1) {
return true;
}
});
console.log(filtered)
//Try with this code
var arr = [1,2, 3,3,4,5,5,5,6,6];
arr = arr.filter( function( item, index, inputArray ) {
return inputArray.indexOf(item) == index;
});
Also look into this link https://fiddle.jshell.net/5hshjxvr/

Completely removing duplicate items from an array

Let's assume that I have ;
var array = [1,2,3,4,4,5,5];
I want it to be;
var newArray = [1,2,3];
I want to remove the duplicates completely rather than keeping them as unique values. Is there a way achieve that through reduce method ?
You could use Array#filter with Array#indexOf and Array#lastIndexOf and return only the values which share the same index.
var array = [1, 2, 3, 4, 4, 5, 5],
result = array.filter(function (v, _, a) {
return a.indexOf(v) === a.lastIndexOf(v);
});
console.log(result);
Another approach by taking a Map and set the value to false, if a key has been seen before. Then filter the array by taking the value of the map.
var array = [1, 2, 3, 4, 4, 5, 5],
result = array.filter(
Map.prototype.get,
array.reduce((m, v) => m.set(v, !m.has(v)), new Map)
);
console.log(result);
I guess it won't have some remarkable performance, but I like the idea.
var array = [1,2,3,4,4,5,5],
res = array.reduce(function(s,a) {
if (array.filter(v => v !== a).length == array.length-1) {
s.push(a);
}
return s;
}, []);
console.log(res);
Another option is to use an object to track how many times an element is used. This will destroy the array order, but it should be much faster on very large arrays.
function nukeDuplications(arr) {
const hash = {};
arr.forEach(el => {
const qty = hash[el] || 0;
hash[el] = qty+1;
});
const ret = [];
Object.keys(hash).forEach(key => {
if (hash[key] === 1) {
ret.push(Number(key));
}
})
return ret;
}
var array = [1,2,3,4,4,5,5];
console.log(nukeDuplications(array));
A slightly more efficient solution would be to loop over the array 1 time and count the number of occurrences in each value and store them in an object using .reduce() and then loop over the array again with .filter() to only return items that occurred 1 time.
This method will also preserve the order of the array, as it merely uses the object keys as references - it does not iterate over them.
var array = [1,2,3,4,4,5,5];
var valueCounts = array.reduce((result, item) => {
if (!result[item]) {
result[item] = 0;
}
result[item]++;
return result;
}, {});
var unique = array.filter(function (elem) {
return !valueCounts[elem] || valueCounts[elem] <= 1;
});
console.log(unique)
Another option is to use an object to track how many times an element is used. This will destroy the array order, but it should be much faster on very large arrays.
// Both versions destroy array order.
// ES6 version
function nukeDuplications(arr) {
"use strict";
const hash = {};
arr.forEach(el => {
const qty = hash[el] || 0;
hash[el] = qty + 1;
});
const ret = [];
Object.keys(hash).forEach(key => {
if (hash[key] === 1) {
ret.push(Number(key));
}
})
return ret;
}
// ES5 version
function nukeDuplicationsEs5(arr) {
"use strict";
var hash = {};
for (var i = 0; i < arr.length; i++) {
var el = arr[i];
var qty = hash[el] || 0;
hash[el] = qty + 1;
};
var ret = [];
for (let key in hash) {
if (hash.hasOwnProperty(key)) {
if (hash[key] === 1) {
ret.push(Number(key));
}
}
}
return ret;
}
var array = [1, 2, 3, 4, 4, 5, 5];
console.log(nukeDuplications(array));
console.log(nukeDuplicationsEs5(array));
There are a lot of over-complicated, and slow running code here. Here's my solution:
let numbers = [1,2,3,4,4,4,4,5,5]
let filtered = []
numbers.map((n) => {
if(numbers.indexOf(n) === numbers.lastIndexOf(n)) // If only 1 instance of n
filtered.push(n)
})
console.log(filtered)
you can use this function:
function isUniqueInArray(array, value) {
let counter = 0;
for (let index = 0; index < array.length; index++) {
if (array[index] === value) {
counter++;
}
}
if (counter === 0) {
return null;
}
return counter === 1 ? true : false;
}
const array = [1,2,3,4,4,5,5];
let uniqueValues = [];
array.forEach(element => {
if(isUniqueInArray(array ,element)){
uniqueValues.push(element);
}
});
console.log(`the unique values is ${uniqueValues}`);
If its help you, you can install the isUniqueInArray function from my package https://www.npmjs.com/package/jotils or directly from bit https://bit.dev/joshk/jotils/is-unique-in-array.
My answer is used map and filter as below:
x = [1,2,3,4,2,3]
x.map(d => x.filter(i => i == d).length < 2 ? d : null).filter(d => d != null)
// [1, 4]
Object.values is supported since ES2017 (Needless to say - not on IE).
The accumulator is an object for which each key is a value, so duplicates are removed as they override the same key.
However, this solution can be risky with misbehaving values (null, undefined etc.), but maybe useful for real life scenarios.
let NukeDeps = (arr) => {
return Object.values(arr.reduce((curr, i) => {
curr[i] = i;
return curr;
}, {}))
}
I would like to answer my questions with an answer I came up with upon reading it again
const array = [1, 2, 3, 4, 4, 5, 5];
const filtered = array.filter(item => {
const { length } = array.filter(currentItem => currentItem === item)
if (length === 1) {
return true;
}
});
console.log(filtered)
//Try with this code
var arr = [1,2, 3,3,4,5,5,5,6,6];
arr = arr.filter( function( item, index, inputArray ) {
return inputArray.indexOf(item) == index;
});
Also look into this link https://fiddle.jshell.net/5hshjxvr/

Is it possible to slightly modify my symmetric difference function so that it can accept an unknown number of arguments?

I've created this codepen http://codepen.io/PiotrBerebecki/pen/ZWxvzm when trying to find an array containing symmetric difference of two or more arrays.
My function works OK but only if four arguments are passed. How can I modify my function so that it can accept an unknown number of arguments? There is a potentially repeatable block of code that perhaps could be part of a for loop or reduce / map methods. I can't figure out how to accomplish this.
symmetricDifference([1,2,3,4], [3,4,5,6], [2,4,6,7], [8,9])
// should return an array containing [1,4,5,7,8,9]
symmetricDifference([1,2,3,4], [3,4,5,6])
// should return an array containing [1,2,5,6]
var arrA = [1,2,3,4];
var arrB = [3,4,5,6];
var arrC = [2,4,6,7];
var arrD = [8,9];
function symmetricDifference(arr) {
let args = Array.prototype.slice.call(arguments);
let result = [];
result = args[0].concat(args[1]).filter(function(item) {
return args[0].indexOf(item) === -1 || args[1].indexOf(item) === -1;
});
result = result.concat(args[2]).filter(function(item) {
return result.indexOf(item) === -1 || args[2].indexOf(item) === -1;
});
result = result.concat(args[3]).filter(function(item) {
return result.indexOf(item) === -1 || args[3].indexOf(item) === -1;
});
return result;
}
Thanks to the hints by #Bergi I've introduced a for loop and an initial value var result = args[0]; The function is working now as desired as it accepts an unknown number of arguments. I've updated the original codepen (http://codepen.io/PiotrBerebecki/pen/ZWxvzm) to demonstrate this implementation.
function symmetricDifference(arr) {
let args = Array.prototype.slice.call(arguments);
let result = args[0];
for (var i = 1; i < args.length; i++) {
result = result.concat(args[i]).filter(function(item) {
return result.indexOf(item) === -1 || args[i].indexOf(item) === -1;
});
}
// remove duplicates and sort
return Array.from(new Set(result)).sort((a, b) => a - b);
}

JavaScript: How to match out-of-order arrays

I'm trying to work out how to match arrays that share the same elements, but not necessarily in the same order.
For example, these two arrays share the same set of elements, even though they're in a different order.
Is there any way to determine whether two arrays contain the same elements?
var search1 = ["barry", "beth", "debbie"];
var search2 = ["beth", "barry", "debbie"];
if (search1 == search2) {
document.write("We've found a match!");
} else {
document.write("Nothing matches");
}
I've got a Codepen of this running at the moment over here: http://codepen.io/realph/pen/grblI
The problem with some of the other solutions is that they are of O(n²) complexity, if they're using a for loop inside of a for loop. That's slow! You don't need to sort either—also slow.
We can speed this up to O(2n) complexity1 by using a simple dictionary. This adds O(2n) storage, but that hardly matters.
JavaScript
var isEqual = function (arr1, arr2) {
if (arr1.length !== arr2.length) {
return false; // no point in wasting time if they are of different lengths
} else {
var holder = {}, i = 0, l = arr2.length;
// holder is our dictionary
arr1.forEach(function (d) {
holder[d] = true; // put each item in arr1 into the dictionary
})
for (; i < l; i++) { // run through the second array
if (!(arr2[i] in holder)) return false;
// if it's not in the dictionary, return false
}
return true; // otherwise, return true
}
}
Test Case
var arr1 = ["barry", "beth", "debbie"],
arr2 = ["beth", "barry", "debbie"];
console.log(isEqual(arr1,arr2));
// returns true
fiddle
Improvement
As Ahruss pointed out, the above function will return true for two arrays that are seemingly equal. For example, [1,1,2,3] and [1,2,2,3] would return true. To overcome this, simply use a counter in the dictionary. This works because !undefined and !0 both return true.
var isReallyEqual = function (arr1, arr2) {
if (arr1.length !== arr2.length) {
return false; // no point in wasting time if they are of different lengths
} else {
var holder = {}, i = 0, l = arr2.length;
// holder is our dictionary
arr1.forEach(function (d) {
holder[d] = (holder[d] || 0) + 1;
// checks whether holder[d] is in the dictionary: holder[d] || 0
// this basically forces a cast to 0 if holder[d] === undefined
// then increments the value
})
for (; i < l; i++) { // run through the second array
if (!holder[arr2[i]]) { // if it's not "in" the dictionary
return false; // return false
// this works because holder[arr2[i]] can be either
// undefined or 0 (or a number > 0)
// if it's not there at all, this will correctly return false
// if it's 0 and there should be another one
// (first array has the element twice, second array has it once)
// it will also return false
} else {
holder[arr2[i]] -= 1; // otherwise decrement the counter
}
}
return true;
// all good, so return true
}
}
Test Case
var arr1 = [1, 1, 2],
arr2 = [1, 2, 2];
isEqual(arr1, arr2); // returns true
isReallyEqual(arr1, arr2); // returns false;
1: It's really O(n+m) complexity, whereby n is the size of the first array and m of the second array. However, in theory, m === n, if the arrays are equal, or the difference is nominal as n -> ∞, so it can be said to be of O(2n) complexity. If you're feeling really pedantic, you can say it's of O(n), or linear, complexity.
you can use this function to compare two arrays
function getMatch(a, b) {
for ( var i = 0; i < a.length; i++ ) {
for ( var e = 0; e < b.length; e++ ) {
if ( a[i] === b[e] ){
return true;
}
}
}
}
Feed your arrays to the following function:
function isArrayEqual(firstArray, secondArray) {
if (firstArray === secondArray) return true;
if (firstArray == null || secondArray == null) return false;
if (firstArray.length != secondArray.length) return false;
// optional - sort the arrays
// firstArray.sort();
// secondArray.sort();
for (var i = 0; i < firstArray.length; ++i) {
if (firstArray[i] !== secondArray[i]) return false;
}
return true;
}
Now you may be thinking, can't I just say arrayOne.sort() and arrayTwo.sort() then compare if arrayOne == arrayTwo? The answer is no you can't in your case. While their contents may be the same, they're not the same object (comparison by reference).
You need to simply sort them, then compare them
function compareArrayItems(array1, array2){
array1 = array1.sort();
array2 = array2.sort();
return array1.equals(array2);
}
fiddle
You can use the equals function provided in How to compare arrays in JavaScript?
Sort them firstly. Secondly, if their length is different, then they're not a match.
After that, iterate one array and test a[i] with b[i], a being the first array, b the second.
var search1 = ["barry", "beth", "debbie"],
search2 = ["beth", "barry", "debbie"];
// If length are different, than we have no match.
if ((search1.length != search2.length) || (search1 == null || search2 == null))
document.write("Nothing matches");
var a = search1.sort(),
b = search2.sort(),
areEqual = true;
for (var i = 0; i < a.length; i++) {
// if any two values from the two arrays are different, than we have no match.
if (a[i] != b[i]) {
areEqual = false;
break; // no need to continue
}
}
document.write(areEqual ? "We've found a match!" : "Nothing matches");

array_count_values for JavaScript instead

I have the following PHP-script, now I need to do the same thing in JavaScript. Is there a function in JavaScript that works similar to the PHP function, I have been searching for days but cannot find anything similar? What I want to do is to count the number of times a certain word is being used in an array.
$interfaceA = array($interfaceA_1,$interfaceA_2,$interfaceA_3,$interfaceA_4,$interfaceA_5,$interfaceA_6,$interfaceA_7,$interfaceA_8);
$interfaceA_array=array_count_values($interfaceA);
$knappsatsA = $interfaceA_array[gui_knappsats];
$touchpanelA = $interfaceA_array[gui_touchpanel];
Why not simply create a new javascript array "counts"
Iterate over original array, and increament the count of "counts" for keys encountered in the array.
http://jsfiddle.net/4t28P/1/
var myCurrentArray = new Array("apple","banana","apple","orange","banana","apple");
var counts = {};
for(var i=0;i< myCurrentArray.length;i++)
{
var key = myCurrentArray[i];
counts[key] = (counts[key])? counts[key] + 1 : 1 ;
}
alert(counts['apple']);
alert(counts['banana']);
Another elegant solution would be to use Array.prototype.reduce.
Given:
var arr = new Array("apple","banana","apple","orange","banana","apple");
You can just run reduce on it:
var groups =
arr.reduce(function(acc,e){acc[e] = (e in acc ? acc[e]+1 : 1); return acc}, {});
Finally you can check the result:
groups['apple'];
groups['banana'];
In the sample above reduce takes two parameters:
a function (anonymous here) taking an accumulator (initialized from the second argument of reduce), and the current array element
the initial value of the accumulator
Whatever the function returns, it will be used as the accumulator value in the next call.
From a type perspective, whatever the type of the array elements, the type of the accumulator must match the type of the second argument of reduce (initial value), and the type of the return value of the anonymous function.
This will also be the type of the return value of reduce.
Try
a.reduce((a,c)=> (a[c]=++a[c]||1,a) ,{});
let a= ["apple","banana","apple","orange","banana","apple"];
let count= a.reduce((a,c)=> (a[c]=++a[c]||1,a) ,{});
console.log(count);
How about this:
function arrayCountValues (arr) {
var v, freqs = {};
// for each v in the array increment the frequency count in the table
for (var i = arr.length; i--; ) {
v = arr[i];
if (freqs[v]) freqs[v] += 1;
else freqs[v] = 1;
}
// return the frequency table
return freqs;
}
let snippet = "HARRY POTTER IS A SERIES OF FANTASY NOVELS WRITTEN BY BRITISH AUTHOR J. K. ROWLING. THE NOVELS CHRONICLE" +
" THE LIVES OF A YOUNG WIZARD, HARRY POTTER , AND HIS FRIENDS HERMIONE GRANGER AND RON WEASLEY, ALL OF WHOM ARE " +
" STUDENTS AT HOGWARTS SCHOOL OF WITCHCRAFT AND WIZARDRY";
String.prototype.groupByWord = function () {
let group = {};
this.split(" ").forEach(word => {
if (group[word]) {
group[word] = group[word] + 1;
} else {
group[word] = 1;
}
});
return group;
};
let groupOfWordsByCount = snippet.groupByWord();
console.log(JSON.stringify(groupOfWordsByCount,null, 4))
This should work
function array_count_values(array) {
var tmpArr = {};
var key = '';
var t = '';
var _countValue = function(tmpArr, value) {
if (typeof value === 'number') {
if (Math.floor(value) !== value) {
return;
}
} else if (typeof value !== 'string') {
return;
}
if (value in tmpArr && tmpArr.hasOwnProperty(value)) {
++tmpArr[value];
} else {
tmpArr[value] = 1;
}
}
for (key in array) {
if (array.hasOwnProperty(key)) {
_countValue.call(this, tmpArr, array[key]);
}
}
return tmpArr;
}
console.log(array_count_values([12, 43, 12, 43, "null", "null"]));

Categories

Resources