0

I'm literally stuck at solving this simple question. Anyway I found out another way to solve this but I couldn't figure out the issue with my code.

function charCout(str)
{
    str = str.toLowerCase();
    var f  = {};

    for(let i =0;i<str.length;i++)
    {
        if(str[i] === " ")
        {
            continue;
        }
        else{
            if(str[i] in Object.keys(f))
            {
                f[str[i]] += 1;
            }
            else
            {
                f[str[i]] = 1;
            }
        }
    }
  return(f);   
}




input: charCout("my name is Khan23")
expected output: {2: 1,3: 1,a: 2,e: 1,h: 1,i: 1,k: 1,m: 2,n: 2,s: 1,y: 1}
what i got: {2: NaN,3: NaN,a: 1,e: 1,h: 1,i: 1,k: 1,m: 1,n: 1,s: 1,y: 1}
Charlie
  • 22,886
  • 11
  • 59
  • 90
Ps Naidu
  • 103
  • 1
  • 5
  • 1
    You want simply `str[i] in f`, not `str[i] in Object.keys(f)`. If you were getting the array of all keys, you'd need to do `Object.keys(f).includes(str[i])` (but that's horribly inefficient). – Bergi Jul 26 '19 at 18:07

6 Answers6

1

Simply see if the property exists by type coercion like: if(f[str[i]])

function charCount(str)
{
    str = str.toLowerCase();
    var f  = {};

    for(let i =0;i<str.length;i++)
    {
        if(str[i] === " ")
        {
            continue;
        }
        else{
            if(f[str[i]])
            {
                f[str[i]] += 1;
            }
            else
            {
                f[str[i]] = 1;
            }
        }
    }
  return(f);   
}

console.log(charCount('the value is 0000'))
Charlie
  • 22,886
  • 11
  • 59
  • 90
0

You are using the wrong to way to check if key is in object or not.

You can contract your if-else to single line using || operator.

f[str[i]] = f[str[i]] + 1 || 1 

It checks whether f[str[i]] already exists or not. If str[i] is not key of f then f[str[i]] will return undefined and undefined + 1 will be NaN.

NaN is a falsy value so NaN || 1 will evaluate to 1.

If the f[str[i]] exists then it will return any number greater than 0 so it will be set to f[str[i]] + 1(incremented by one)

function charCount(str)
{
    str = str.toLowerCase();
    var f  = {};

    for(let i =0;i<str.length;i++)
    {
        if(str[i] !== " ")
        {
            f[str[i]] = f[str[i]] + 1 || 1 
        }
    }
  return(f);   
}
console.log(charCount("my name is Khan23"))

Explanation:

You can also use reduce().

const charCount = str => str
                          .split(' ')
                          .join('')
                          .split('')
                          .reduce((ac,a) => 
                              (ac[a] = ac[a] + 1 || 1, ac), 
                          {})


console.log(charCount("my name is Khan23"))
Community
  • 1
  • 1
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
  • 2
    `||` doesn't check whether the key exists. If you really want to do it like this, please explain how exactly it works. – Bergi Jul 26 '19 at 18:09
  • @Bergi I have added an explanation. – Maheer Ali Jul 26 '19 at 18:15
  • Thanks. I would think `f[str[i]] = (f[str[i]] || 0) + 1` is better to understand, though. Or just go for the explicit `(str[i] in f ? f[str[i]] : 0) + 1` – Bergi Jul 26 '19 at 18:18
  • I did it exactly the same way you did @maheer. I don't have problem with this method. I'm just trying to figure out what's the issue with the above code(my code) – Ps Naidu Jul 26 '19 at 20:50
0

You can use str.split("") to get the list of chars and then do something like

const splitted = str.split("");
const result = {};
splitted.map(letter => result[letter] ? result[letter]++ : result[letter] = 1)

it is just an idea

Community
  • 1
  • 1
Emanuele Scarabattoli
  • 4,103
  • 1
  • 12
  • 21
0

using Object.keys(f).includes(str[i]) instead of str[i] in Object.keys(f) is the solution

in operator primarily would work to check if Object provides a particular attribute

Mozilla doc on in and Array.prototype.includes shall help.

following variation of your function would work

function charCout(str)
{
    str = str.toLowerCase();
    var f  = {};

    for(let i =0;i<str.length;i++)
    {
        if(str[i] === " ")
        {
            continue;
        }
        else{
            if(Object.keys(f).includes(str[i]))
            {
                f[str[i]] += 1;
            }
            else
            {
                f[str[i]] = 1;
            }
        }
    }
  return(f);   
}
AbhishekKr
  • 300
  • 2
  • 12
  • Ty abhishek. Now i figured out the issue with my code. we can't filter array with the value at index using "in" operator. – Ps Naidu Jul 26 '19 at 21:13
0

You can take advantage of String.protoype.split and Array.prototype.reduce to solve this. Check the comments in the code for details:

const charCount = s => {
  //Create an array of characters found in the string (filtering out spaces)
  const chars = s.split('').filter(char => char.trim());

  //Use reduce to create an occurrence map - increment by 1 each time a character is encountered
  return chars.reduce((accum, char) => {
    accum[char] = accum[char] ? accum[char] + 1 : 1;
    return accum;
  }, {});
};

console.log(charCount("my name is Khan23"))
Tom O.
  • 5,730
  • 2
  • 21
  • 35
0

Thank you all for your helpful suggestions. i finally figured out whats wrong with my code.

inputs and outputs of my defected code is as follows:

input: charCout("my name is Khan23")

expected output: {2: 1,3: 1,a: 2,e: 1,h: 1,i: 1,k: 1,m: 2,n: 2,s: 1,y: 1}

what i got: {2: NaN,3: NaN,a: 1,e: 1,h: 1,i: 1,k: 1,m: 1,n: 1,s: 1,y: 1};

I've used "in" operator to find out whether a specific value of string is present the Object.keys(f) array. That's exactly where I went wrong.

after referring to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in i got to know "in" can't be used to filter array using value at index.

Ps Naidu
  • 103
  • 1
  • 5