Enthu
Enthu

Reputation: 532

Counting the occurrence of chars in a javascript string

I have written down code to calculate the count of each of the character in a string. It seems to be working correctly for some of the words where as for some it fails.

It fails for the last character, as I see the length of the string becomes smaller than the iteration count (but for some of the words)

var str1 = "america"

function noofchars(str1) {
  for (var m = 0; m < str1.length + 1; m++) {
    var countno = 1;
    if (m != 0) {
      str1 = str1.slice(1)
    }

    str2 = str1.substr(0, 1)

    for (var i = 0; i < str1.length; i++) {
      if (str2 === str1.charAt(i + 1)) {
        countno += 1
        str1 = str1.slice(0, i + 1) + str1.slice(i + 2) + " "
      }
    }
    console.log(str1.charAt(0) + "=" + countno)
  }
}

var findnoofchar = noofchars(str1)

It passes for london, philadelphia, sears, happy But fails for america, chicago etc london = l=1, o=2, n=2, d=1

Upvotes: 2

Views: 636

Answers (3)

WZLWebNmedia
WZLWebNmedia

Reputation: 21

Not really knowing what you are trying to accomplish with your code, one solution is to utilize the charAt and Set functions. CharAt is a more direct way to iterate over the string and the Set function eliminates duplicate characters from the set automatically.

var str1 = "america";
    
      function noofchars(str1) {
        var charList = new Set();
        for (var m = 0; m < str1.length; m++) {
          
          var charX = str1.charAt(m).substr(0, 1);
          var countno = 1;
    
          for (var i = 0; i < str1.length; i++) {
            if (str1.slice(0, i + 1) == charX) {
              countno++;
            }
            charList.add(charX + "=" + countno);
          }
        }
        // you may need to expand set on Chrome console
        console.log(charList);
        // a hack to display more easily display on your screen
        var listOnScreen = Array.from(charList);
        document.getElementById('displaySet').innerHTML=listOnScreen;
      }
    
      noofchars(str1);
<div id="displaySet"></div>

Upvotes: 0

fyasir
fyasir

Reputation: 2970

You can split the string by each character and then count the number of occurrence of each character by reduce function as below

function noofchars(str1) {
  const chArray = str1.split('');
  return chArray.reduce(function(acc, ch) {
    if (acc[ch]) {
      acc[ch]++;
    } else {
      acc[ch] = 1;
    }
    return acc;
  }, {});
 }

 var str1 = "america";
 var findnoofchar = noofchars(str1);
 console.log(findnoofchar);

In your solution you are mutating str1 in this line

str1 = str1.slice(0, i + 1) + str1.slice(i + 2) + " "

which actually changes the length of the string and also checking str1.length in the first loop. In you case you can take the length in the first place. Working version of your code snippet is here

var str1 = "america"

function noofchars(str1) {
  const len = str1.length;
  for (var m = 0; m < len; m++) {
    var countno = 1;
    if (m !== 0) {
      str1 = str1.slice(1)
    }
    if (str1.charAt(0) === ' ') {
      break;
    }
    str2 = str1.substr(0, 1)

    for (var i = 0; i < str1.length; i++) {
      if (str2 === str1.charAt(i + 1)) {
        countno += 1
        str1 = str1.slice(0, i + 1) + str1.slice(i + 2) + " "
      }
    }
    console.log(str1.charAt(0) + "=" + countno)
  }
}

var findnoofchar = noofchars(str1)

Upvotes: 0

Jack Bashford
Jack Bashford

Reputation: 44145

It'd be easier to use an object. First reduce into character counts, then iterate through the key/value pairs and console.log:

function noofchars(str1) {
  let r = [...str1].reduce((a, c) => (a[c] = (a[c] || 0) + 1, a), {});
  Object.entries(r).forEach(([k, v]) => console.log(`${k}=${v}`));
}
noofchars("america");

ES5 syntax:

function noofchars(str1) {
  var r = str1.split("").reduce(function(a, c) {
    a[c] = (a[c] || 0) + 1;
    return a;
  }, {});
  Object.keys(r).forEach(function(k) {
    console.log(k + "=" + r[k]);
  });
}
noofchars("america");

It's easier to understand what reduce is doing in the above snippet.

First, we take a function with two parameters a and c. These can be called anything, I just use a and c for the accumulator and the current item.

Now, the second line:

a[c] = (a[c] || 0) + 1;

This is kind hard, so let's break it down. First let's look at what's in the parentheses:

a[c] || 0

This checks if a has a key/value pair with the key c (as in, the value of c, not the key literally being c). If that doesn't exist, it returns 0. So if a[c] exists, save it as the value of the expression, otherwise use 0.

Now, we add 1, to increment the value.

Finally, we assign the result to a[c]. So if a contained c, the value of a[c] would be incremented. If a didn't contain c, the value of a[c] would be 1.

Then, we return a to be used in the next iteration of reduce.

In the next line:

}, {});

We assign a default value for a. If we didn't do this, the first time reduce ran, a would be "a", and c would be "m" (the first two characters of america). This way, a is {} (an empty object), and c is "a". If we didn't have this second argument, our function wouldn't work.

In this line:

Object.keys(r).forEach(function(k) {...});

We're getting an array of all the keys in r, and looping through them with forEach, with k being the key.

Then, we're logging k (the key), then an equals sign =, then the value of r[k].

Upvotes: 5

Related Questions