# Reduce exercise, how should I do?

Hello! Can you explain to me how should I solve these what am I doing wrong??

``````const isPresent = function(string, target) {
const letters = string.split('');
console.log(letters);
letters.reduce((acc,curr)=> {
console.log(acc)
if(acc===target){
return acc=true;
} else {
return acc=curr;
}

return acc;
})
}

isPresent('abcd', 'b') // => true

const countLetters = function(string){
let count={};
const letters = string.split('');
console.log(letters);
let obj = letters.reduce((acc, curr)=>{
console.log(acc)
if (acc.hasOwnProperty(acc[curr])){
return acc[curr] += 1;
} else {
return acc[curr]=1;
}
return acc;
}, count)
};

countLetters('abbcccddddeeeee') // => {a:1, b:2, c:3, d:4, e:5}
``````

Solution for the first problem (in case someone will wonder):

``````const isPresent = function(string, target) {
const letters = string.split('');
console.log(letters);
let boo= letters.reduce((acc,curr)=> {

if(curr===target){
return acc=true;
} return acc;
}, false);
return boo;
}
``````

for the second, down in the comment, there is the solution. Thank you everyone who helped me! First thing that stands out for me is that you’re using assignment operator `=` in return statement. Try using strict equality `===` instead the output shoud be true or false, if the acc is equal to target then change the acc to be true (so I reassign it ) I don’t know, maybe I didnt get what you wanted to say

I would suggest l logging out data to see what is happening:

``````const countLetters = function (string) {
let count = {};
const letters = string.split("");
console.log(letters);
let obj = letters.reduce((acc, curr) => {
if (acc.hasOwnProperty(acc[curr])) {
console.log('incrementing', acc, curr);
return (acc[curr] += 1);
} else {
console.log('initializing', acc, curr);
return (acc[curr] = 1);
}
console.log('Can this code *ever* be hit?');
return acc;
}, count);
return obj;
};
console.clear();
console.log(countLetters("abbcccddddeeeee"));
``````

Ultimately I was able to get this to work by fixing three lines.

``````    if (acc.hasOwnProperty(acc[curr])) {
``````

Is that what you want to check? Do you want to check if it has the property of `acc[curr]`? Ask yourself what that variable contains.

``````      return (acc[curr] += 1);
``````

and

``````      return (acc[curr] = 1);
``````

For example, put a console.log before that second one and see what `acc[curr] = 1` evaluates to. Remember that what we return here is what the new acc will become. We don’t need to change the current acc, we just need to return what we want the acc to be in the next iteration.

I did this the console.log shows the obj with the letter counted but don’t know why I cant take them out, also if i return if and else blocks I get a 1 in console.log, but not anything in the obj, why is this??

``````
const countLetters = function(string){
let count={};
const letters = string.split('');
console.log(letters);
let obj = letters.reduce((acc, curr)=>{
/* console.log(curr) */
console.log(acc)

if (Object.keys(acc).includes(curr)){
acc[curr]= acc[curr]+1;
}else{
acc[curr]= 1;
}

return acc;
}, count)
};

countLetters('abbcccddddeeeee')
``````

Still, you’re trying to assign what you want. Don’t. Return what you want. And what is acc? It’s an object … so you have to return an object. How do you make a new object with that new property? There are a couple ways, but I think it would be a nice chance to use a spread operator.

You are better off with the `hasOwnProperty` method here. Converting the object back into an array and using `indexOf` on it is overly complicated and less efficient than just checking if the letter exists in the object using `hasOwnProperty`.

Because, `return (acc[curr] = 1);` is returning 1 because `acc[curr] = 1` evaluates to 1 and that’s what you’re telling reduce that you want the next acc to be.

Yes, the prototype methods are a little confusing, and none of them are worse than reduce. I’ve even met senior devs that didn’t know how to use it. But it is learnable and it is very powerful.

Actually, your latest version is basically working, you just forgot to return the result from _ countLetters_.

1 Like

so here am I turning the obj into an arr that why it doesn’t work in if/else? I wanted to use this `acc[curr] = 1` to set the first value to one in case I see that key for the first time.

Omg!! Thanks! I thought the reduce was wrong I couldn’t see. It is 2/3 days that I am trying to learn how to use reduce, so I am still confuse.

so here am I turning the obj into an arr that why it doesn’t work in if/else?

That isn’t turning the object into anything - it is returning the keys and leaving the object unaffected. That isn’t a problem. But I think Randy is right - _ hasOwnProperty_ is better - you were just checking for the wrong property.

I wanted to use this `acc[curr] = 1` to set the first value to one in case I see that key for the first time.

That’s fine the way you have that now - it just didn’t work when you were trying to return that expression directly.

1 Like

I wanted to use this `acc[curr] = 1` to set the first value to one in case I see that key for the first time.

To be clear, there is a difference between:

``````return acc[curr] = 1;
``````

and

``````acc[curr] = 1;
return acc;
``````

In the first one, you’re altering acc but returning what the expression `acc[curr] = 1` evaluates to (the number 1). In the second one you’re altering acc again and then returning acc.

I got now, thank you for helping me and your time!

1 Like

And one last point, actually I think the cleanest version of this:

``````    if (Object.keys(acc).includes(curr)){
``````

would be:

``````   if (acc[curr]) {
``````

Once it’s set, it will always be truthy.

1 Like

thanks! Yes, that is a good advise