Return values from array and occurences by frequency [duplicate]

早过忘川 提交于 2019-12-08 07:58:02

问题


So i have this code

Array.prototype.byCount= function(){
    var itm, a= [], L= this.length, o= {};
    for(var i= 0; i<L; i++){
        itm= this[i];
        if(!itm) continue;
        if(o[itm]== undefined) o[itm]= 1;
        else ++o[itm];
    }
    for(var p in o) a[a.length]= p;
    return a.sort(function(a, b){
        return o[b]-o[a];
    });
}

source

This is almost what i need except that it does not return the number of occurences with the value.

I tried to rewrite it, but i always fail at the sorting part.

Thanks for your help


回答1:


This should do what you want:

Array.prototype.byCount= function(){
    var itm, a= [], L= this.length, o= {};
    for(var i= 0; i<L; i++){
        itm= this[i];
        if(!itm) continue;
        if(o[itm]== undefined) o[itm]= 1;
        else ++o[itm];
    }
    for(var p in o) a[a.length]= {item: p, frequency: o[p]};
    return a.sort(function(a, b){
        return o[b.item]-o[a.item];
    });
}

Test:

var A= ["apples","oranges","oranges","oranges","bananas","bananas","oranges"];
A.byCount()

Produces:

[ { frequency: 4, item: "oranges" }, { frequency: 2, item: "bananas"}, {frequency: 1, item: "apples"} ]

Edit

Doing return o[b.item]-o[a.item]; is completely overcomplicated an pointless as Bergi points out in comments. return b.frequency - a.frequency; would have been better.




回答2:


You can include the frequencies and simplify the code a bit by doing the following:

Array.prototype.byCount = function() {
  var o = {};

  this.filter(function(el) { return el; }).forEach(function(el) {
      o[el] = (o[el] || 0) + 1;
  });

  return Object.keys(o).map(function (key) {
      return { key: key, occurrences: o[key] };
  }).sort(function(a, b) {
    return b.occurrences - a.occurrences;
  });
}

console.log(JSON.stringify([1, 2, null, 9, 9, undefined, 9, 9, 1, 3, 1, 1, 9, 2].byCount()));

Result:

[{"key":"9","occurrences":5},
 {"key":"1","occurrences":4},
 {"key":"2","occurrences":2},
 {"key":"3","occurrences":1}]

If you have Lo-Dash available, you can do this a bit more cleanly:

Array.prototype.byFreq = function () {
  var grouped = _.groupBy(_.compact(this)),
      pairs = _.map(grouped, function (vals, key) { 
          return { key: key, occurrences: vals.length }
      }),
      sorted = _.sortBy(pairs, function (pair) { 
          return -pair.occurrences 
      });
  return sorted;
};

console.log(JSON.stringify([1,2,9,9, null, 9,9,1,3, undefined, 1,1,9,2].byFreq()));
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>



回答3:


If you want to add the occurence counts to the values, you'd either put them together at the end:

return a.sort(function(a, b){
    return o[b]-o[a];
}).map(function(v) {
    return {value: v, count: o[v]}
});

or put them in the array right away and adapt the comparison function:

for (var p in o)
    a.push({value: p, count: o[p]});
return a.sort(function(a, b){
    return a.count-b.count;
});


来源:https://stackoverflow.com/questions/28077040/return-values-from-array-and-occurences-by-frequency

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!