计算字符串中每个字符出现的次数

31

我希望使用JavaScript计算给定字符串中每个字符出现的次数。

例如:

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

输出结果应为:

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

我尝试在 Google 上搜索,但没有找到答案。我想要实现类似这个的功能;顺序不重要。

25个回答

31

使用 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}

欢迎来到SO。如果您在回答问题时包含更多代码解释,那么您的答案将会更有用。 - Nick
10
我宁愿执行 [...s].reduce((res, char) => (res[char] = (res[char] || 0) + 1, res), {}) 这段代码。 - Yevhen Horbunkov
请注意,结果不是数组,因此您不能使用result.length,而是要检查长度,您将使用Object.keys(result).length - Avatar

26

这在JavaScript中很简单(或任何其他支持任意键/值映射的语言)。对于键/值映射,在JavaScript中有两个选项:对象和Map实例。在大多数情况下,如果键是任意的,像这种情况一样,Map是更好的选择(更多信息请参见MDN)。下面是它的代码:

// 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;
}

使用 Map,迭代的顺序将是将键添加到 Map 中的顺序。您可以在上面看到,I 是我们在输出中看到的第一个字符,后跟一个空格,然后是 w...
这是使用对象的情况,但要注意不要将对象用于任意键/值映射,并且如果您以这种方式使用它们,请创建没有原型的对象,以便它们不具有继承属性(请参见上面的 MDN 链接了解详细信息):

// 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;
}

它们被添加的顺序也将是对象属性的顺序,除了那些作为数组索引合格的数字字符串属性名称将首先按升序访问。以下是使用上述两个选项处理字符串"abc321"的结果-请注意结果顺序的差异:

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;
}


1
这真的很好。即使在2022年,它仍然有效--我不确定其机制,但会将其加入书签以供参考和稍后检查。 - Eric Hepperle - CodeSlayer2010
1
@EricHepperle-CodeSlayer2010 - 谢谢!由于那个评论让我回到了答案,我对它进行了现代化改进——在过去的九年中,JavaScript已经有了很大的提高。 :-) 原来的方法仍然有效(现代JavaScript是99.999%向后兼容的),但是通过使用新的特性,我们可以获得更可靠的结果,而且代码可以更加简洁。 - T.J. Crowder

8
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)

6
我遍历每个字符并将其与计数一起放入嵌套对象中。如果字符已经存在于对象中,我只需增加计数。 这是我的 myObj 对象的样子:
myObj = {
char1 = { count : <some num> },
char2 = { count : <some num> },
....
}

以下是代码:

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');

5

您可以在JavaScript的ES6中使用地图。在我看来,它提供了更干净和简洁的代码。以下是我的方法:

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

这对我很有帮助:

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));

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
感谢这段代码片段,它可能会提供一些有限的、即时的帮助。通过展示为什么这是一个好的解决方案并使其对未来有类似问题的读者更有用,适当的解释将极大地提高其长期价值。请编辑您的答案添加一些解释,包括您所做的假设。 - Syscall

2

我给你非常简单的代码。

 // 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
请解释一下这个答案! - Mazz

2
一行ES6的方式:
const some_string = 'abbcccdddd';
const charCountIndex = [ ...some_string ].reduce( ( a, c ) => ! a[ c ] ? { ...a, [ c ]: 1 } : { ...a, [ c ]: a[ c ] + 1 }, {} );
console.log( charCountIndex )

2

我使用了Map对象,这个对象不允许你设置重复的键,这使得我们的工作变得更加容易。我正在检查该键是否已经存在于Map中,如果不存在,我将插入并将计数设置为1;如果已经存在,则获取该值并进行递增。

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)
    })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接