【问题标题】:Counting frequency of characters in a string using JavaScript使用 JavaScript 计算字符串中字符的频率
【发布时间】:2013-09-04 17:02:06
【问题描述】:

我需要编写某种循环来计算字符串中每个字母出现的频率。

例如:"aabsssd"

输出:a:2, b:1, s:3, d:1

还想在对象中映射与属性名称相同的字符。有什么好主意吗?

我不知道该怎么做。

这是我目前的位置:

var arr = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];

function counter(x) {
  var count = 0,
    temp = [];
  x = x.split('');
  console.log(x);
  for (var i = 0, len = x.length; i < len; i++) {
    if (x[i] == "a") {
      count++;
    }
  }
  return count;
}
var a = "aabbddd";
console.log(counter(a));

【问题讨论】:

标签: javascript


【解决方案1】:

给你:

function getFrequency(string) {
    var freq = {};
    for (var i=0; i<string.length;i++) {
        var character = string.charAt(i);
        if (freq[character]) {
           freq[character]++;
        } else {
           freq[character] = 1;
        }
    }

    return freq;
};

【讨论】:

  • 谁能解释一下上述代码中的 if (freq[character]) 是如何工作的。它完美地解决了我的问题。我使用调试器来了解它是如何工作的。但仍然没有得到它背后的逻辑。谢谢
  • 在 javascript 中,undefined 值等于 false。通过检查if(freq[character]),您正在检查freq[character] 的值是否为假(即:undefined、0、null 等)。由于我们在1 处初始化了匹配字符的值,因此只有在之前遇到并计算过该字符时才会输入 if 语句,否则我们将其初始化
  • 上面的代码可以用一个衬里替换(freq[character] = freq[character] + 1 || 1)它可以工作,但是当我用 freq[character] = freq[character]++ 替换时|| 1 它应该可以工作,但它并不总是对所有字符都计为 1。为什么?你能解释一下吗?
【解决方案2】:

一些带有reduce的ES6语法:

let counter = str => {
  return str.split('').reduce((total, letter) => {
    total[letter] ? total[letter]++ : total[letter] = 1;
    return total;
  }, {});
};

counter("aabsssd"); // => { a: 2, b: 1, s: 3, d: 1 }

【讨论】:

    【解决方案3】:

    另一种解决方案:

    function count (string) {  
      var count = {};
      string.split('').forEach(function(s) {
         count[s] ? count[s]++ : count[s] = 1;
      });
      return count;
    }
    

    【讨论】:

      【解决方案4】:

      具有一些 ES6 特性和短路功能:

      const counter = s => [...s].reduce((a, c) => (a[c] = a[c] + 1 || 1) && a, {})
      
      console.log(
        counter("hello") // {h: 1, e: 1, l: 2, o: 1}
      )  

      【讨论】:

      • 我在上面的代码中有一个查询 (a[c] = a[c] + 1 || 1) 它可以工作,但是当我替换为 a[c] = a[c]+ + || 1 它应该可以工作,但它并不总是对所有 char 计数 1。为什么?你能解释一下吗?
      • @Infinity x++ 递增并返回 x 的 old 值。所以 x = x++ 将增加 x 并再次将其设置为旧值。将其更改为 ++x,它应该可以工作。
      【解决方案5】:

      这是另一种方式:

      const freqMap = s => [...s].reduce((freq,c) => {freq[c] = -~freq[c]; return freq} ,{})
      

      或者,如果您更喜欢“for”循环:

      function freqMap(s) { 
         freq={}; 
         for (let c of s) 
            freq[c]=-~freq[c]; 
         return freq;
      }
      

      例如freqMap("MaMaMia") 返回Object{M : 3, a : 3, i : 1}

      此方法利用了这样一个事实,即在 javascript 中,按位不在“未定义”上给出 -1,(而“未定义 + 1”给出 NaN)。 所以,-~undefined1-~12-~23 等等。

      因此,我们可以遍历字符串的字符,并简单地递增freq[c] 而无需任何“if”。我们第一次遇到字符cfreq[c] 将是未定义的,所以我们将其设置为-~freq[c],即1。如果我们随后再次遇到c,我们再次将freq[c] 设置为-~freq[c],现在将是2,等等。

      简单、优雅、简洁。

      【讨论】:

        【解决方案6】:

        获取单词直方图的更具说明性的方法是利用 reduce 遍历字母并提出一个包含字母作为键和频率作为值的新对象。

        function getFrequency(str) {
          return str.split('').reduce( (prev, curr) => {
            prev[curr] = prev[curr] ? prev[curr] + 1 : 1;
            return prev;
          }, {});
        };
        
        console.log(getFrequency('test')); // => {t: 2, e: 1, s: 1}

        【讨论】:

          【解决方案7】:

          更精简、更实用的解决方案:

          使用 ES6 箭头 && 逻辑运算符:

          const buildFreqDict = string =>
            string.split('').reduce((freqDict, char) => {
              freqDict[char] = (freqDict[char] || 0) + 1;
              return freqDict;
            }, {})
          
          console.log(buildFreqDict("banana"))

          解释

          • 拆分 字符串 成字符数组。
            • 然后将其输入 reduce 方法(使用 method.chaining())。
          • 如果 char 已经登录 countDict 则加 1。
            • 如果在 countDict 中找不到字符,则将其设置为 1。
          • 将新值返回到 reduce 的累加器对象
          • 注意:不要忘记包含 .reduce() 的第三个参数:在这种情况下,它是一个 {}(对象字面量),用于初始化 freqDict 对象。

          有关更多信息,请参阅计算对象中值的实例在页面的中间:MDN Reduce
          有关使用逻辑运算符的更多信息,请参阅此处:MDN Logical Operators

          【讨论】:

            【解决方案8】:

            一个简单的方法。此外,它还为您提供按字母顺序排序的列表。它遍历一个数组并评估字符是否已经在对象中:如果为 false,则将字符添加到对象中,如果为 true,则其频率增加一个单位。

            const text= "Lorem ipsum dolor sit amet consectetur adipiscing"
            const textAsArray = text.split('').sort()
            let charactersList = {}
            
            for (char of textAsArray) {
            
               if (!charactersList[char]) {
                charactersList[char]=1;
               }
               else {
                charactersList[char]++
              }
            }
            
            console.log(charactersList)   
            

            【讨论】:

              【解决方案9】:

              我已经审查过,我认为这非常适合他们提出的需求。我希望它在一行中,但我不知道如何动态生成对象。

              const uniqueCount=(arr)=>{
              let rs ={};
              arr.sort().join("").match(/(.)(\1*)/g).map(i=>rs[i[0]]=i.length);
              return rs;
              };
              console.log(uniqueCount(["a","b","c","d","d","e","a","b","c","f","g","h","h","h","e","a"]));
              //{ a: 3, b: 2, c: 2, d: 2, e: 2, f: 1, g: 1, h: 3 }

              我发现如上所述使用.match() 和正则表达式/(.)(\1*)/g 非常成功。

              如果只是一个字符串,你只需要在前面加上一个.split("")就可以了。

              【讨论】:

                【解决方案10】:

                还有一个按字母顺序排序的版本。此功能适用于两者。

                1. 按字母顺序排列的字符频率
                2. 按出现顺序排列的字符频率

                警告:仅当整个字符串为小写时才有效

                function freqWithAlphabetTable(str, doNeedToSort) {
                    let cnt = new Array(26).fill(0), firstLowerCase = 97, output = {}
                    for (let i = 0; i < str.length; i++)
                        cnt[str[i].charCodeAt(0) - firstLowerCase]++ // filling the array with count at it's index
                    if (doNeedToSort) {
                        for (let i = 0; i < cnt.length; i++) {
                            if (cnt[i] !== 0)
                                output[String.fromCharCode(firstLowerCase)] = cnt[i]
                            firstLowerCase++;
                        }
                    } else {
                        for (let i = 0; i < str.length; i++) {
                            let letterIndexVal = cnt[str[i].charCodeAt(0) - firstLowerCase];
                            if (letterIndexVal != 0 ) {
                                output[str[i]] = letterIndexVal
                                letterIndexVal = 0 // replacing it with zero to avoid repetition
                            }
                        }
                    }
                    console.log(output);
                    return output;
                }
                

                【讨论】:

                  【解决方案11】:
                  for(i = strlen(string)var string = 'aabsssd';
                  var chars = new Array();
                  for(var i = 0; i < string.length; i++){
                      var char = string.charAt(i);
                      if(chars[char] == undefined){
                          chars[char] = 0;
                      }
                      chars[char]++;
                  }
                  console.log(chars);
                  

                  【讨论】:

                    【解决方案12】:

                    这是另一个使用 underscore.js 的选项:

                    function charCount(str) {
                        return _(str.split('')).countBy(function(char) {
                            return char.toLowerCase();
                        });
                    }
                    

                    charCount('aaabbbbdd') 输出Object {a: 3, b: 4, d: 2}

                    【讨论】:

                      【解决方案13】:

                       const recorrences = ['a', 'b', 'c', 'a', 'b','a']
                                      .map(i => !!~i.indexOf('a'))
                                      .filter(i => i)
                                      .length;
                      console.log(`recorrences ${recorrences}`) 
                      //recorrences 3

                      【讨论】:

                        【解决方案14】:
                        // Count frequency of characters in a string
                        // input: 'Hello, I'm Paul!'
                        // result: {
                        //      H: 1,
                        //      E: 1,
                        //      L: 3,
                        //      ... and so on ...
                        // }
                        
                        const countChars = (string) => {
                            let charStats = {};
                            string = string.replace(' ', '').toUpperCase().split('');
                        
                            string.forEach((char) => {
                                if (charStats[char]) {
                                    charStats[char]++;
                                } else {
                                    charStats[char] = 1;
                                }
                            });
                        
                            return charStats;
                        };
                        

                        【讨论】:

                          【解决方案15】:

                          另一种解决方案

                              function maxChar(str) {
                          
                                  const charMap = {};
                                  let max = 0;
                                  let maxChar = '';
                          
                                  for(let char of str){
                                      if(charMap[char]){
                                          charMap[char]++;
                                      }else{
                                          charMap[char] = 1;
                                      }
                                  }
                          
                                  for(let char in charMap){
                                      if(charMap[char] > max){
                                          max = charMap[char];
                                          maxChar = char;
                                      }
                                  }
                          
                                  return maxChar; 
                          }
                          

                          ===>

                           maxChar('355385') 
                            "5"
                          

                          【讨论】:

                            【解决方案16】:
                            var str = 'abcccdddd';
                            
                            function maxCharCount(target) {
                                const chars = {};
                            
                                let maxChar = '';
                                let maxValue = 1;
                            
                                for (let char of target) {
                                    chars[char] = chars[char] + 1 || 1;
                                }
                            
                                return chars;
                            }
                            
                            console.log(maxCharCount(str));
                            

                            【讨论】:

                              【解决方案17】:

                              相同的解决方案,但重构。太酷了,我们如何用这么多不同的答案来解决这个问题:)

                              function getFrequency(string) {
                              
                                  var freq = {};
                              
                                  for (let character in string) {
                              
                                       let char = string[character];        
                                       (freq[char]) ? freq[char]++ : freq[char] = 1
                              
                                  }
                              
                                  return freq;
                              
                              };
                              

                              【讨论】:

                                【解决方案18】:

                                你可以使用它。只需传递字符串,它将返回具有所有字符频率的对象。

                                function buildCharMap(string) {
                                  const charMap = {};
                                  string.replace(/[^\w]/g, '').toLowerCase();
                                  for (let char of string) {
                                    charMap[char] = charMap[char] + 1 || 1;
                                  }
                                  return charMap;
                                }
                                

                                【讨论】:

                                  【解决方案19】:
                                   [...str].map( char => map.get(char) ? map.set( char, map.get(char) + 1) : map.set(char,1) ) 
                                  

                                  【讨论】:

                                  • 虽然这个答案解决了这个问题,但如果你可以编辑它并添加关于该代码如何帮助的解释,我会改进很多
                                  【解决方案20】:

                                  计算字符串中字符频率的作弊码是

                                  let target = "e";
                                  let string = " i want to see that person that came in here last";
                                  let frequency = string.split(target).length - 1;
                                  

                                  或全部在一行

                                  console.log(string.split("e").length - 1)
                                  

                                  【讨论】:

                                  • 这实际上是假的,返回 7 而不是 6
                                  • @JorelAmthor 刚刚编辑了我的答案,总是从长度减去 1,并注意 -1,表示没有匹配项
                                  猜你喜欢
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2016-05-18
                                  • 2017-04-19
                                  • 2011-10-06
                                  • 2019-08-07
                                  • 1970-01-01
                                  • 2023-03-25
                                  相关资源
                                  最近更新 更多