最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Counting all characters in a string - Stack Overflow

programmeradmin1浏览0评论

I want to count all characters in a string and return it to an object. I have tried but I’m unable to get the correct answer.

This is my code:

function countAllCharacters(str) {
  var a = str.split("");
  var obj = {};
  a.forEach(function(s){
    var count=0;
    for(var j=0;j<a.length;j++){
      if(s==a[j]){
        count+=1;
      }
      obj[a[j]]=count;
    }
  });
  return obj;
}
console.log(countAllCharacters('banana'));

I want to count all characters in a string and return it to an object. I have tried but I’m unable to get the correct answer.

This is my code:

function countAllCharacters(str) {
  var a = str.split("");
  var obj = {};
  a.forEach(function(s){
    var count=0;
    for(var j=0;j<a.length;j++){
      if(s==a[j]){
        count+=1;
      }
      obj[a[j]]=count;
    }
  });
  return obj;
}
console.log(countAllCharacters('banana'));

Output:

{ b: 0, a: 3, n: 2 } 

Which obviously is wrong.

Can anyone help me with that? Where I am going wrong?

Share Improve this question edited Jun 13, 2017 at 4:25 Sebastian Simon 19.5k8 gold badges60 silver badges84 bronze badges asked Jun 13, 2017 at 4:20 Kartik ChorasiyaKartik Chorasiya 291 gold badge1 silver badge2 bronze badges 5
  • 2 Why are you using a nested loop? – nnnnnn Commented Jun 13, 2017 at 4:25
  • can you please elaborate and give the right code? – Kartik Chorasiya Commented Jun 13, 2017 at 4:26
  • 2 You really just need nothing but obj[s] = (obj[s] || 0) + 1; in the forEach callback. Counting characters is usually done with reduce instead of forEach, though. – Sebastian Simon Commented Jun 13, 2017 at 4:27
  • See counting frequency of characters in a string using javascript for a number of alternative solutions. – RobG Commented Jun 13, 2017 at 4:34
  • Just place obj[a[j]]=count; out of the for loop – Black Mamba Commented Jun 13, 2017 at 4:35
Add a comment  | 

10 Answers 10

Reset to default 6

The minimum necessary change is that obj[a[j]]=count; should be obj[s]=count;, because you have that line running on every iteration of the inner loop regardless of whether j refers to the letter you're currently tallying.

function countAllCharacters(str) {
  var a = str.split("");
  var obj = {};
  a.forEach(function(s){
    var count=0;
    for(var j=0;j<a.length;j++){
      if(s==a[j]){
        count+=1;
      }
      obj[s]=count;
    }
  });
  return obj;
}
console.log(countAllCharacters('banana'));

However, you don't need a nested loop. Your outer .forEach() can update the count for the current letter directly:

function countAllCharacters(str) {
  var a = str.split("");
  var obj = {};
  a.forEach(function(s){
    obj[s] = (obj[s] || 0) + 1;
  });
  return obj;
}
console.log(countAllCharacters('banana'));

This can be made shorter with .reduce():

function countAllCharacters(str) {
  return str.split("").reduce(function(obj, s){
    obj[s] = (obj[s] || 0) + 1;
    return obj;
  }, {});
}
console.log(countAllCharacters('banana'));

Note that (obj[s] || 0) means to use obj[s]'s value if it is truthy, otherwise use 0. So the first time you encounter a particular letter obj[s] will be undefined, which is falsey, so then 0 will be used. The next time you encounter that letter obj[s] will be 1, which is truthy.

Actually you can count by better performance, you loop more than you needed!

function countAllCharacters(str) {
  var a = str.split("");
  var obj = {};
  for(var j=0;j<a.length;j++){
    if(typeof obj[a[j]] !== 'undefined'){
      obj[a[j]]+=1;
    } else {
      obj[a[j]]=1;
     }
  }
  return obj;
}
console.log(countAllCharacters('banana'));

I'd use a reduce operation, like so

const str = "banana"
const charCounts = Array.from(str).reduce((counts, char) => {
  counts[char] = (counts[char] || 0) + 1
  return counts
}, Object.create(null))

console.info(charCounts)

I think you need not to use a forEach and a for loop together when you can do it with only foreach. Here is the code.

function countAllCharacters(str) {
  var a = str.split("");
  var obj = {};
  a.forEach(function(s) {
    if (obj[s]) {
      obj[s] = obj[s] + 1;
    } else {
      obj[s] = 1;
    }
  });
  return obj;
}

console.log(countAllCharacters('banana'));

Hope it helps :)

The problem here is that you assign the obj[a[j]] = count; when the counting is not yet complete. You should do change your function(s) to this:

  function(s){
    var count=0;
    for(var j=0;j<a.length;j++){
      if(s==a[j]){
        count+=1;
      }
    }
    obj[s]=count;
  }

Another comment: you code is very inefficient, which is O(n^2). You can simplify it much further to get an O(n) algorithm with this:

  function(s){
    if (obj[s] == undefined) {
       obj[s] = 1;
    } else {
       obj[s] = obj[s] + 1;
    } 
  }

Already so many friends submitted their opinions and cool solutions. Here is my solution with the simplest code:

const src = 'banana';

const count = str => 
  [...str].reduce((acc, val) => (acc[val] ? (acc[val]++) : (acc[val]=1), acc),{});
  
console.log(count(src));
.as-console-wrapper {min-height: 100%}

Hope you enjoy my code. Thanks.

I realize this isn't the prettiest, but I'm hoping it shows how you can use console to help debug loops.

function countAllCharacters(str) {
  var a = str.split("");
  var obj = {};
  a.forEach(function(s){
  console.log(s);
    var count=0;
    for(var j in a){

      // commas can come in really handy and help avoid huge debug blocks.
      console.log('_',j,s,a[j]); 

      if(s==a[j]){
        console.log('count++');
        count++;
      }
      obj[s] = count;
    }
  });
  return obj;
}

console.log(countAllCharacters('banana'));

you have to bring obj[a[j]]=count inside your if statement.

this should return correct results

function countAllCharacters(str) {
  var a = str.split("")
  var obj = {}
  a.forEach(function(s){
    var count=0
    for(var j=0;j<a.length;j++){
      if(s===a[j]){
        count+=1
        obj[a[j]]=count
      }
    }
  })
  return obj
}
console.log(countAllCharacters('banana'))

the increment in obj must also satisfy the if statement.

function countAllCharacters(str) {
   let newArr = str.split('');  // splits the string into a new array
   let obj = {};  // initiliza an empty object

   newArr.forEach(char => (obj[char]) ? obj[char] += 1 : obj[char] = 1);
   return obj; 
}
 let name = "banana";
 // First we have to remove space from the string
 name = name.replace(/\s/g, "");
 for (let i = 0; i < name.length; i++) {
   let count = 0;
   for (let j = 0; j < name.length; j++) {
     if (name[i] == name[j] && i > j) {
       break;
     }
     if (name[i] == name[j]) {
       count++
     }
   }
   if (count) {
     console.log(name[i], count);
   }
 }
发布评论

评论列表(0)

  1. 暂无评论