JavaScript统计字符串字母出现次数时结果重复输出如何解决
问题描述
编写JavaScript代码统计字符串中各字母的出现次数时,代码运行后会重复输出每个字母的统计结果,预期要实现的效果是汇总相同字母的出现频次,每个字母仅展示一次对应的统计值。
问题原代码
const string = 'mississippi' const letters = [...string] let currentLetter = '' let letterOccurance = [] for(let i = 0; i < letters.length; i++){ let letterFrequency = letters.filter((letter)=>{ return letter === letters[i] }) letterOccurance.push([`${letters[i]}`,letterFrequency.length]) } console.log(letterOccurance)
原代码运行后会输出长度为11的二维数组(和mississippi的字符串长度一致),同一个字母的统计结果会重复出现多次,比如字母s会有4条值为4的重复记录,字母i会有4条值为4的重复记录,和预期效果不符。
问题原因
遍历逻辑没有加去重判断:循环每走到一个字符位置,不管这个字符之前有没有统计过,都会重新遍历整个数组过滤出当前字符计算频次,再把结果推入结果数组,最终同一个字母的统计值会重复出现和它频次相等的次数。另外原代码里声明的currentLetter变量全程没有被使用,属于冗余代码。
修复方案
方案1:最小改动适配原有代码逻辑
只需要在推入统计结果前,先检查结果数组里是不是已经存过当前字母的统计记录,如果已经存在就直接跳过当前轮次,不再重复统计、重复推入即可。
修改后可直接运行的代码:
const string = 'mississippi' const letters = [...string] // 删除未使用的currentLetter变量 const letterOccurance = [] for(let i = 0; i < letters.length; i++){ const currentChar = letters[i] // 校验当前字母是否已经完成统计 const alreadyCounted = letterOccurance.some(record => record[0] === currentChar) if (alreadyCounted) continue // 仅对未统计过的字母计算频次并存入结果 const letterFrequency = letters.filter(letter => letter === currentChar) letterOccurance.push([currentChar, letterFrequency.length]) } console.log(letterOccurance) // 输出:[ [ 'm', 1 ], [ 'i', 4 ], [ 's', 4 ], [ 'p', 2 ] ],符合预期
方案2:更高性能的实现方式(推荐)
原实现每次统计都要全量遍历数组过滤,性能较差,可以用普通对象存频次,仅需遍历一次字符串就能完成统计,时间复杂度从O(n²)降到O(n):
const string = 'mississippi' const frequencyMap = {} for (const char of string) { // 已记录的字母频次+1,未记录的初始值设为1 frequencyMap[char] = (frequencyMap[char] || 0) + 1 } // 转成和原逻辑一致的二维数组格式 const letterOccurance = Object.entries(frequencyMap) console.log(letterOccurance) // 输出:[ [ 'm', 1 ], [ 'i', 4 ], [ 's', 4 ], [ 'p', 2 ] ]
内容的提问来源于stack exchange,提问作者marsprogrammer
相关产品推荐
相关产品推荐

