Counting the occurrences / frequency of array elements

前端 未结 30 2526
甜味超标
甜味超标 2020-11-21 06:47

In Javascript, I\'m trying to take an initial array of number values and count the elements inside it. Ideally, the result would be two new arrays, the first specifying each

相关标签:
30条回答
  • 2020-11-21 07:18

    Edit 2020: this is a pretty old answer (nine years). Extending the native prototype will always generate discussion. Although I think the programmer is free to choose her own programming style, here's a (more modern) approach to the problem without extending Array.prototype:

    {
      // create array with some pseudo random values (1 - 5)
      const arr = Array.from({length: 100})
        .map( () => Math.floor(1 + Math.random() * 5) );
      // frequencies using a reducer
      const arrFrequencies = arr.reduce((acc, value) => 
          ({ ...acc, [value]: acc[value] + 1 || 1}), {} )
      console.log(`Value 4 occurs ${arrFrequencies[4]} times in arrFrequencies`);
    
      // bonus: restore Array from frequencies
      const arrRestored = Object.entries(arrFrequencies)
        .reduce( (acc, [key, value]) => acc.concat(Array(value).fill(+key)), [] );
      console.log(arrRestored.join());  
    }
    .as-console-wrapper { top: 0; max-height: 100% !important; }

    The old (2011) answer: you could extend Array.prototype, like this:

    {
      Array.prototype.frequencies = function() {
        var l = this.length,
          result = {
            all: []
          };
        while (l--) {
          result[this[l]] = result[this[l]] ? ++result[this[l]] : 1;
        }
        // all pairs (label, frequencies) to an array of arrays(2)
        for (var l in result) {
          if (result.hasOwnProperty(l) && l !== 'all') {
            result.all.push([l, result[l]]);
          }
        }
        return result;
      };
    
      var freqs = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4].frequencies();
      console.log(`freqs[2]: ${freqs[2]}`); //=> 5
      
      // or
      var freqs = '1,1,2,one,one,2,2,22,three,four,five,three,three,five'
        .split(',')
        .frequencies();
        
      console.log(`freqs.three: ${freqs.three}`); //=> 3
      
    // Alternatively you can utilize Array.map:
    
        Array.prototype.frequencies = function() {
          var freqs = {
            sum: 0
          };
          this.map(function(a) {
            if (!(a in this)) {
              this[a] = 1;
            } else {
              this[a] += 1;
            }
            this.sum += 1;
            return a;
          }, freqs);
          return freqs;
        }
    }
    .as-console-wrapper { top: 0; max-height: 100% !important; }

    0 讨论(0)
  • 2020-11-21 07:19

    Using Lodash

    const values = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
    const frequency = _.map(_.groupBy(values), val => ({ value: val[0], frequency: val.length }));
    console.log(frequency);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

    0 讨论(0)
  • 2020-11-21 07:20

    There is a much better and easy way that we can do this using ramda.js. Code sample here

    const ary = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]; R.countBy(r=> r)(ary) countBy documentation is at documentation

    0 讨论(0)
  • 2020-11-21 07:21

    I know this question is old but I realized there are too few solutions where you get the count array as asked with a minimal code so here is mine

    // The initial array we want to count occurences
    var initial = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];  
    
    // The count array asked for
    var count = Array.from(new Set(initial)).map(val => initial.filter(v => v === val).length);  
    
    // Outputs [ 3, 5, 1, 1 ]
    

    Beside you can get the set from that initial array with

    var set = Array.from(new Set(initial));  
    
    //set = [5, 2, 9, 4]  
    
    0 讨论(0)
  • const data = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]
    
    function count(arr) {
      return arr.reduce((prev, curr) => (prev[curr] = ++prev[curr] || 1, prev), {})
    }
    
    console.log(count(data))

    0 讨论(0)
  • 2020-11-21 07:26

    I was solving a similar problem on codewars and devised the following solution which worked for me.

    This gives the highest count of an integer in an array and also the integer itself. I think it can be applied to string array as well.

    To properly sort Strings, remove the function(a, b){return a-b} from inside the sort() portion

    function mostFrequentItemCount(collection) {
        collection.sort(function(a, b){return a-b});
        var i=0;
        var ans=[];
        var int_ans=[];
        while(i<collection.length)
        {
            if(collection[i]===collection[i+1])
            {
                int_ans.push(collection[i]);
            }
            else
            {
                int_ans.push(collection[i]);
                ans.push(int_ans);
                int_ans=[];
            }
            i++;
        }
    
        var high_count=0;
        var high_ans;
    
        i=0;
        while(i<ans.length)
        {
            if(ans[i].length>high_count)
            {
                high_count=ans[i].length;
                high_ans=ans[i][0];
            }
            i++;
        }
        return high_ans;
    }
    
    0 讨论(0)
提交回复
热议问题