Count characters in a string This code is supposed to count each character in a given string and account for error handling and type casting as well, and it should do it in the most efficient manner possible, with O(n) being an upper limit for both time and memory. I have gone through my process for problem solving which involves explaining the problem in my own words, looking at the inputs, the outputs, if the answer is even possible given the I/O, and then refactoring my code. Please, if anyone sees a better way to accomplish this then let me know.



function characterCounter(str) {
    // Error Handling
    // No input
    if (!str) {
        return "String input required";
    }

    // attempt to type cast non strings
    if (typeof str !== "string") {
        str = str.toString();
        // input could not be successfully type casted
        if (typeof str !== "string") {
            return "Invalid input";
        }
    }

    const stringLen = str.length;
    const result = {};
    let i = 0;

    // loop through each character for O(n) time complexity and O(n) space complexity
    // since the object grows based on input size
    for (; i &lt; stringLen; i++) {
        // If string not in object as a key then add it and set value to 1
        if (result[str[i]] === undefined &amp;&amp; str[i] !== " ") {
            result[str[i].toLowerCase()] = 1;
        } else {
            if (str[i] !== " ") {
                // add one to value at current key
                result[str[i]]++;
            }
        }
    }
    return result;
}

// Returns an object which allows O(1) for insert, deletion, access, and O(n) for searching...
console.log(characterCounter("Hello, World!"));
The algorithm is not working quite as you may expect:


   if (result[str[i]] === undefined &amp;&amp; str[i] !== " ") {
        result[str[i].toLowerCase()] = 1;
    } else {
        if (str[i] !== " ") {
            // add one to value at current key
            result[str[i]]++;
        }
    }



If you enter "Hello, World! - Hi!" the two upper case 'H' are only counted as one, because they both evaluate to true in the first if-statement - because you test for an upper case 'H' but save a lower case 'h'.

In the same place you filter spaces out both in true and false, so you could do that as the first thing to do in the loop.

All in all that could be like: 

  for (; i &lt; stringLen; i++) {
    let ch = str[i].toLowerCase();
    if (ch !== " ") {
      if (result[ch] === undefined) {
        result[ch] = 1;
      } else {
        result[ch]++;
      }
    }
  }




Use comments to explain why you do what you do (if not obvious), and not what you do - the code shows that.



The whole ting could also be done like this:

function characterCounter(str) {
  if (!str) {
    return "String input required";
  }

  if (typeof str !== "string") {
    str = str.toString();
    if (typeof str !== "string")
      return "Invalid input";
  }

  const result = {};

  for (var i in str) {
    var ch = str[i].toLowerCase();
    if (ch !== " ") {
      if (result[ch] === undefined) {
        result[ch] = 1;
      } else {
        result[ch]++;
      }
    }
  }
  return result;
}