29

I want to count the number of occurrences of each character in a given string using JavaScript.

For example:

var str = "I want to count the number of occurrences of each char in this string";

Output should be:

h = 4;
e = 4; // and so on 

I tried searching Google, but didn't find any answer. I want to achieve something like this; order doesn't matter.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
JS-coder
  • 3,243
  • 2
  • 14
  • 14

24 Answers24

29

Shorter answer, with reduce:

let s = 'hello';
var result = [...s].reduce((a, e) => { a[e] = a[e] ? a[e] + 1 : 1; return a }, {}); 
console.log(result); // {h: 1, e: 1, l: 2, o: 1}
Avatar
  • 14,622
  • 9
  • 119
  • 198
Vitaly Volynsky
  • 393
  • 3
  • 3
  • Welcome to SO. Your answer will be more useful if you include more explanation of how your code answers the question. – Nick Apr 05 '19 at 17:27
  • 10
    I would rather do `[...s].reduce((res, char) => (res[char] = (res[char] || 0) + 1, res), {})` – Yevhen Horbunkov Jun 03 '19 at 08:30
  • Note that the result is not array, so you cannot use `result.length`, instead to check the length you would use `Object.keys(result).length`. – Avatar Jan 29 '20 at 10:39
24

This is nice and simple in JavaScript (or any other language that supports arbitrary key/value maps). And for key/value mapping, in JavaScript you have two options: objects and Map instances. In most cases where the keys are arbitrary as in this case, a Map is the better choice (more on MDN). Here's how that looks:

// The string
const str = "I want to count the number of occurrences of each char in this string";

// A map for the character=>count mappings
const counts = new Map();

// Loop through the string...
for (const ch of str) {
    // Get the count for it, if we have one; we'll get `undefined` if we don't
    // know this character yet. Using nullish coalescing (`??`), we can turn
    // that `undefined` into a `0`. (In obsolete environments that don't
    // support nullish coalescing, for this use case we could use the logical
    // OR operator [`||`] instead to use `0` instead of any falsy value, since
    // A) `undefined` is falsy, and B) None of the count values we're tracking
    // will be falsy because they're all non-zero. For some other use cases,
    // we'd need to use a conditional testing `undefined` explicitly.)
    const count = counts.get(ch) ?? 0;

    // Add one and store the result
    counts.set(ch, count + 1);
}

// Show the counts
for (const [ch, count] of counts) {
    console.log(`"${ch}" count: ${counts.get(ch)}`);
}
.as-console-wrapper {
    max-height: 100% !important;
}

With a Map, the order of the iteration at the end will be the order in which the keys were first added to the Map. You can see that above, I is the first character we see in the output, followed by a space, followed by w...

Here's what it looks like with an object, but beware of using objects for arbitrary key/value maps, and if you use them that way, create them without a prototype so they don't have inherited properties (see the MDN link above for details):

// The string
const str = "I want to count the number of occurrences of each char in this string";

// An object for the character=>count mappings
// We use `Object.create(null)` so the object doesn't have any inherited properties
const counts = Object.create(null);

// Loop through the string...
for (const ch of str) {
    // Get the count for it, if we have one; we'll get `undefined` if we don't
    // know this character yet. Using nullish coalescing (`??`), we can turn
    // that `undefined` into a `0`. (In obsolete environments that don't
    // support nullish coalescing, for this use case we could use the logical
    // OR operator [`||`] instead to use `0` instead of any falsy value, since
    // A) `undefined` is falsy, and B) None of the count values we're tracking
    // will be falsy because they're all non-zero. For some other use cases,
    // we'd need to use a conditional testing `undefined` explicitly.)
    const count = counts[ch] ?? 0;

    // Add one and store the result
    counts[ch] = count + 1;
}

// Show the counts
for (const ch in counts) {
    console.log(`"${ch}" count: ${counts[ch]}`);
}
.as-console-wrapper {
    max-height: 100% !important;
}

The order of that will also be the order the objects properties were first added except that property names that are numeric strings qualifying as array indexes will be visited first, in ascending numeric order. Here's both options above processing the string "abc321" — notice the difference in the order of the results:

function withAMap(str) {
    // A map for the character=>count mappings
    const counts = new Map();

    // Loop through the string...
    for (const ch of str) {
        // Get the count for it, if we have one; we'll get `undefined` if we don't
        // know this character yet. Using nullish coalescing (`??`), we can turn
        // that `undefined` into a `0`. (In obsolete environments that don't
        // support nullish coalescing, for this use case we could use the logical
        // OR operator [`||`] instead to use `0` instead of any falsy value, since
        // A) `undefined` is falsy, and B) None of the count values we're tracking
        // will be falsy because they're all non-zero. For some other use cases,
        // we'd need to use a conditional testing `undefined` explicitly.)
        const count = counts.get(ch) ?? 0;

        // Add one and store the result
        counts.set(ch, count + 1);
    }

    // Show the counts
    for (const [ch, count] of counts) {
        console.log(`"${ch}" count: ${counts.get(ch)}`);
    }
}

function withAnObject(str) {
    // An object for the character=>count mappings
    // We use `Object.create(null)` so the object doesn't have any inherited properties
    const counts = Object.create(null);

    // Loop through the string...
    for (const ch of str) {
        // Get the count for it, if we have one; we'll get `undefined` if we don't
        // know this character yet. Using nullish coalescing (`??`), we can turn
        // that `undefined` into a `0`. (In obsolete environments that don't
        // support nullish coalescing, for this use case we could use the logical
        // OR operator [`||`] instead to use `0` instead of any falsy value, since
        // A) `undefined` is falsy, and B) None of the count values we're tracking
        // will be falsy because they're all non-zero. For some other use cases,
        // we'd need to use a conditional testing `undefined` explicitly.)
        const count = counts[ch] ?? 0;

        // Add one and store the result
        counts[ch] = count + 1;
    }

    // Show the counts
    for (const ch in counts) {
        console.log(`"${ch}" count: ${counts[ch]}`);
    }
}

const str = "abc321";
console.log("With a Map:");
withAMap(str);
console.log("With an object:");
withAnObject(str);
.as-console-wrapper {
    max-height: 100% !important;
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • This is really good. Even in 2022 it still works -- I'm not sure the mechanics, but bookmarking to reference and examine later – Eric Hepperle - CodeSlayer2010 Nov 23 '22 at 19:37
  • 1
    @EricHepperle-CodeSlayer2010 - Thanks! Since that comment brought me back to the answer, I've modernized it -- JavaScript has improved a lot in the last nine years. :-) The original way still worked (modern JavaScript is 99.999% backward compatible), but with newer features we can get a more reliable result in terms of the order of the counts we get, and the code can be a bit more concise. – T.J. Crowder Nov 24 '22 at 07:35
6
let str = "atul kumar srivastava";
let obj ={};
for(let s of str)if(!obj[s])obj[s] = 1;else obj[s] = obj[s]  + 1;
console.log(obj)
4

You can use the maps in ES6 in Javascript. Provides a cleaner and concise code in my opinion. Here is how I would go about

function countChrOccurence ('hello') {
 let charMap = new Map();
 const count = 0;
  for (const key of str) {
   charMap.set(key,count); // initialize every character with 0. this would make charMap to be 'h'=> 0, 'e' => 0, 'l' => 0, 
  }

  for (const key of str) {
    let count = charMap.get(key);
    charMap.set(key, count + 1);
  }
// 'h' => 1, 'e' => 1, 'l' => 2, 'o' => 1

  for (const [key,value] of charMap) {
    console.log(key,value);
  }
// ['h',1],['e',1],['l',2],['o',1]
}  

4

I iterated over each character and put it in a nested object along with the count. If the character already exists in the object, I simply increment the count. This is what myObj looks like:

myObj = {
char1 = { count : <some num> },
char2 = { count : <some num> },
....
}

Here is the code:

function countChar(str) {
    let myObj= {};
    for (let s of str) {
        if ( myObj[s] ? myObj[s].count ++ : myObj[s] = { count : 1 } );
    }
    return myObj;
}

var charCount = countChar('abcceddd');
3

This worked well for me :

function Char_Count(str1) {
    var chars = {};
    str1.replace(/\S/g, function(l){chars[l] = (isNaN(chars[l]) ? 1 : chars[l] + 1);});
    return chars;
}

var myString = "This is my String";
console.log(Char_Count(myString));
kevinSpaceyIsKeyserSöze
  • 3,693
  • 2
  • 16
  • 25
2

I am giving you very very simple code.

 // Converts String To Array
        var SampleString= Array.from("saleem");

        // return Distinct count as a object
        var allcount = _.countBy(SampleString, function (num) {
            return num;
        });

        // Iterating over object and printing key and value
        _.map(allcount, function(cnt,key){
            console.log(key +":"+cnt);
        });

        // Printing Object
        console.log(allcount);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

    <p>Set the variable to different value and then try...</p>
    
2

I have used Map object , The map object doesn't let you set any duplicate key and that makes our job easy . I am checking if the key already exists in map , if not I am inserting and setting the count to 1 , if it already exists I am getting the value and then incrementing

const str = "Hello H"
    const strTrim = str.replace(/\s/g,'') // HelloH
    const strArr=strTrim.split('')

    let myMap = new Map(); // Map object 

    strArr.map(ele=>{
    let count =0
    if(!myMap.get(ele)){
    myMap.set(ele,++count)
    }else {
    let cnt=myMap.get(ele)
    myMap.set(ele,++cnt)
    }
    console.log("map",myMap)
    })
Vishwanath
  • 176
  • 1
  • 14
2
str = "aaabbbccccdefg";

words = str.split("");

var obj = [];

var counter = 1, jump = 0;

for (let i = 0; i < words.length; i++) {
    if (words[i] === words[i + 1]) {
        counter++;
        jump++;
    }
    else {
        if (jump > 0) {
            obj[words[i]] = counter;
            jump = 0;
            counter=1
        }
        else
            obj[words[i]] = 1;
    }

}
console.log(obj);
  • 1
    Thank you for this code snippet, which might provide some limited, immediate help. A [proper explanation](https://meta.stackexchange.com/q/114762/9193372) would greatly improve its long-term value by showing why this is a good solution to the problem and would make it more useful to future readers with other, similar questions. Please edit your answer to add some explanation, including the assumptions you’ve made. – Syscall Mar 22 '21 at 16:35
2

A 1-liner ES6 way:

const some_string = 'abbcccdddd';
const charCountIndex = [ ...some_string ].reduce( ( a, c ) => ! a[ c ] ? { ...a, [ c ]: 1 } : { ...a, [ c ]: a[ c ] + 1 }, {} );
console.log( charCountIndex )
Siddharth Thevaril
  • 3,722
  • 3
  • 35
  • 71
2

You can use an object for a task.

Step 1 - create an object

step 2 - traverse through a string

Step 3 - add character as key and character count as value in the object

var obj={}

function countWord(arr)
{
for(let i=0;i<arr.length;i++)
{
if(obj[arr[i]]) //check if character is present in the obj as key
{
    obj[arr[i]]=obj[arr[i]]+1; //if yes then update its value
}
else
{
    obj[arr[i]]=1; //initialise it with a value 1

}
}
}

Pranay kumar
  • 1,983
  • 4
  • 22
  • 51
1
    function cauta() {

        var str = document.form.stringul.value;
        str = str.toLowerCase();
        var tablou = [];

        k = 0;
        //cautarea caracterelor unice
        for (var i = 0, n = 0; i < str.length; i++) {
            for (var j = 0; j < tablou.length; j++) {
                if (tablou[j] == str[i]) k = 1;
            }
            if (k != 1) {
                if (str[i] != ' ')
                    tablou[n] = str[i]; n++;
            }
            k = 0;
        }
        //numararea aparitilor
        count = 0;
        for (var i = 0; i < tablou.length; i++) {
            if(tablou[i]!=null){
            char = tablou[i];
            pos = str.indexOf(char);
            while (pos > -1) {
                ++count;
                pos = str.indexOf(char, ++pos);

            }

            document.getElementById("rezultat").innerHTML += tablou[i] + ":" + count + '\n';
            count = 0;
        }
        }

    }

This function will put each unique char in array, and after will find the appearances of each char in str. In my Case, i get and put data into

Dumitru Boaghi
  • 183
  • 2
  • 4
1

 // Converts String To Array
        var SampleString= Array.from("saleem");

        // return Distinct count as a object
        var allcount = _.countBy(SampleString, function (num) {
            return num;
        });

        // Iterating over object and printing key and value
        _.map(allcount, function(cnt,key){
            console.log(key +":"+cnt);
        });

        // Printing Object
        console.log(allcount);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

    <p>Set the variable to different value and then try...</p>
    
1

Hope this helps someone

function getNoOfOccurences(str){
    var temp = {};
    for(var oindex=0;oindex<str.length;oindex++){
        if(typeof temp[str.charAt(oindex)] == 'undefined'){
            temp[str.charAt(oindex)] = 1;
        }else{
            temp[str.charAt(oindex)] = temp[str.charAt(oindex)]+1;
        }
    }
    return temp;
}
Parthasarathy K
  • 121
  • 1
  • 10
1
    package com.company;

import java.util.HashMap;


 public class Main {

    public static void main(String[] args) {
    // write your code here
    HashMap<Character, Integer> sHashMap = new HashMap();  // using hashMap<key , value > here key = character and  value = count

    String arr = "HelloWorld";

    for (int i = 0; i < arr.length(); i++) {
        boolean flag = sHashMap.containsKey(arr.charAt(i));  // check if char is already  present 

    if (flag == true)
        {
            int Count = sHashMap.get(arr.charAt(i)); // get the char count
            sHashMap.put(arr.charAt(i), ++Count); //   increment the count and update in hashMap
        } 
        else 
        {
            sHashMap.put(arr.charAt(i), 1); //if  char not present then insert into hashMap
        }
    }

     System.out.println(sHashMap);
    //OutPut would be like ths {r=1, d=1, e=1, W=1, H=1, l=3, o=2}

}

}
  • Hey there! This is a code only answer which has very little value to anyone else. Might I request you to include some explanation around _what_ the code does? Thanks! – 10 Rep Feb 01 '21 at 17:29
1
let newStr= "asafasdhfasjkhfweoiuriujasfaksldjhalsjkhfjlkqaofadsfasasdfas";
       
function checkStringOccurnace(newStr){
    let finalStr = {};
    let checkArr = [];
    let counterArr = [];
    for(let i = 0; i < newStr.length; i++){
        if(checkArr.indexOf(newStr[i]) == -1){
            checkArr.push(newStr[i])
            let counter = 0;
            counterArr.push(counter + 1)
            finalStr[newStr[i]] = 1;
        }else if(checkArr.indexOf(newStr[i]) > -1){
            let index = checkArr.indexOf(newStr[i])
            counterArr[index] = counterArr[index] + 1;
            finalStr[checkArr[index]] = counterArr[index];
        }
    }
    return finalStr;
}

let demo = checkStringOccurnace(newStr);
console.log(" finalStr >> ", demo);
Blizzardengle
  • 992
  • 1
  • 17
  • 30
  • While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. – Cookie Mar 23 '21 at 17:10
  • This is a great answer to an old question. I would recommend fixing your formatting and adding some comments. Also, if your going to provide a function its best to return something and do the console log outside the function as an example. – Blizzardengle Mar 24 '21 at 03:34
1

I tried it with chceking "empty space" as well as "special characters":

function charCount(str){
    const requiredString = str.toLowerCase();

    const leng = str.length;

    let output = {};

    for(let i=0; i<leng; i++){
        const activeCharacter = requiredString[i];
        if(/[a-z0-9]/.test(activeCharacter)){
            output.hasOwnProperty(activeCharacter) ? output[activeCharacter]++ : output[activeCharacter] = 1;
        }
    }
    return output;
}
Narayan Shrestha
  • 733
  • 8
  • 19
0

Split the string with the spread ... operator instead of .split(''):

''.split('')
//=> ["\ud83c", "\udf2f", "\ud83c", "\udf2f", "\ud83c", "\udf63", "\ud83c", "\udf7b"]

vs

[...'']
//=> ["", "", "", ""]

vs

''.charAt(0)
//=> "\ud83c"

Then reduce:

[...''].reduce((m, c) => (m[c] = (m[c] || 0) + 1, m), {})
//=> {'': 2, '': 1, '': 1}
customcommander
  • 17,580
  • 5
  • 58
  • 84
0

To check and avoid spaces and convert capital letters to small and count we can do like below.

function CountNumberOfCharacters(str) {
  let countObject = {};
  const lowerCaseString = str.toLowerCase();
  for (let char of lowerCaseString) {
    if (!countObject[char] && char !== ' ') {
      countObject[char] = 1;
    } else if (char !== ' ') {
      countObject[char] = countObject[char] + 1;
    }
  }
  return countObject;
}
Sharad Pawar
  • 290
  • 1
  • 2
  • 16
0

Here is the simple and easiest solution, You can find n numbers of strings alphabet, number, special character's etc. Total count in any position. Thanks

let stringValue = "AAABCCDDDDDDFFFGGG333333++++";
let stringArray = stringValue.split("");
let stringCompressorArray = [];
for (let value of stringArray) {
  let stringFindeArray = stringArray.filter((str) => {
    return str === value;
  });
  let repeatValueCounter = stringFindeArray.length + value;
  if (stringCompressorArray.indexOf(repeatValueCounter) < 0) {
    stringCompressorArray.push(repeatValueCounter);
  }
}
let result = stringCompressorArray.join(", ");
console.log("result", result);
hemant rao
  • 2,233
  • 2
  • 13
  • 14
0

Quick, concise and easy to understand

var str = "a a  a   d";

const countChars = str =>{
    const rs = {}
    for (let word of str) {
        if (word !== " ") rs[word] = rs[word] + 1|| 1;
    }
    return rs;
}
countChars(str)
0

Try This

let txt = 'hello';
let txtArr = txt.split('');
let objCnt = txtArr.reduce((accum, currVal) => {
    accum[currVal] = (accum[currVal] || 0) + 1;
    return accum;
}, {});
console.log(objCnt);
Vibhu kumar
  • 386
  • 3
  • 8
0

I thing minimum line of code is best solution. like this.

let text= 'I want to count the number of occurrences of each char in this string';

const obj = {};

for (let i = 0; i < text.length; i++) {
    const ele = text[i];
    obj[ele] === undefined ? obj[ele] = 1 : obj[ele]++
}

console.log(obj);

second example.

text.split('').forEach((ele) => {
    obj[ele] === undefined ? obj[ele] =1 : obj[ele]++ 
})
console.log(obj);
0
               let str = "aabbcc"
                 let obj = {}
               for (let item of str) {
                if (!obj[item]) {
                 obj[item] = 1
                } else {
               obj[item] = obj[item] + 1
                       }
                      }
               console.log(obj)
  • The formatting makes this difficult to understand. It's also highly recommended to explain a bit about your solution, and what makes it different from the other answers that may not have been considered – Kieran101 Mar 30 '23 at 07:02