Reputation: 2087
I'm trying to write a function which will take in an array and then return a map of the frequencies of each object in the array. For example, for the following array:
freqs([1, 2, 3, 7, 2, 7, 1, 2, 1])
it will return a map like the following:
Map {1 => 3, 2 => 3, 3 => 1, 7 => 2}
Here is what I have so far:
function freqs(items) {
return items.reduce(function(prev, curr)
{
if (curr in prev)
{
prev[curr]++;
}
else
{
prev[curr]=1;
}
return prev.map();
});
}
However, when I try to test it, I get the following error:
Uncaught TypeError: Cannot use 'in' operator to search for '1' in 1
What is causing this? Also, is my logic correct? I feel like I'm doing something wrong.
Upvotes: 2
Views: 1389
Reputation: 1
You can use Array.prototype.reduce()
to set property of object to value of array element, increment value for each matched element; Object.keys()
, Array.prototype.forEach()
to set value of Map
var freq = (arr) => {
var map = new Map();
var obj = {};
Object.keys(arr.reduce((obj, prop) => {
return (prop in obj ? ++obj[prop] : (obj[prop] = 1)), obj
}, obj)).forEach(el => map.set(el, obj[el]));
return map
};
var arr = [1, 2, 3, 7, 2, 7, 1, 2, 1];
console.log(freq(arr));
Upvotes: 1
Reputation: 239573
If you don't provide an initial value to reduce
, it will by default use the first element as the initial value. In your case, prev
becomes 1
. Thats why you are getting this error. You should set the initial value to a Map
object.
prev.map()
- I have no clue what the intention is
When you do prev[curr]
, you are using the prev
as a normal JavaScript object. Maps
don't have bracket notation to access their values.
Your fixed program would look like this
function freqs(items) {
return items.reduce(function(prev, c) {
if (prev.has(c)) { // use `has` and `set` operations on Map objects
prev.set(c, prev.get(c) + 1);
} else {
prev.set(c, 1);
}
return prev; // return the map, so it will be prev for the next iteration
}, new Map()); // Set the initial value to a new Map object
}
console.log(freqs([1, 2, 3, 7, 2, 7, 1, 2, 1]));
// Map { 1 => 3, 2 => 3, 3 => 1, 7 => 2 }
Upvotes: 3
Reputation: 1777
You are inconsistantly using c
vs curr
and p
vs prev
.
You are using map the wrong way.
Instead, just return prev;
Next up, you need to set a initial value for the prev
-variable. This should be an empty object {}
as a second argument for reduce
. Do this, and you should be fine.
function freqs(items) {
return items.reduce(function(prev, curr)
{
if (curr in prev)
{
prev[curr]++;
}
else
{
prev[curr]=1;
}
return prev;
},{});
}
Upvotes: 1