3

我想为此使用下划线,但出于某种愚蠢的原因,它使我无法理解:

我有一个数字列表:39、39、10、1、3、4、5...等

我想返回最频繁的 3 个和不太频繁的 3 个。

我尝试过使用 _.countBy ,但它以某种方式返回了一个对象,这使得排序变得困难(?),除非我可能错过了显而易见的事情。

4

2 回答 2

9

叫我疯了,但这是一个没有下划线的解决方案,它不是特别快,因为我排序而O(n log n)不是搜索最大的三个,O(n)但如果它真的很重要,我可以修复它。

让我们的数组是:

var arr = [1,1,1,1,1,1,2,3,4,5,6,7,7,8,9,10,9,8,9,8]

首先,我们将数字减少到它们的频率:

var t =arr.reduce(function(a,b){
    a[b] = (b in a) ? a[b]+1 : 1; // set to 1 if not there, else increase
    return a; // return the object
},{});

var res = Object.keys(t).sort(function(x,y){ // sort by frequency
   return t[x] > t[y]; 
});
// Res more generally contains the frequencies ordered
alert(res[0]+" "+res[1]+" "+res[2]); 

这是一个小提琴。

好吧,所以我撒了谎——我是原生 JavaScript 的傻瓜,这里是“更简单”的下划线版本:

obj = _.countBy(arr,function(num){return num; }); // get array by frequencies
var res = _.keys(obj).sort(function(x,y){ return obj[x] - obj[y]});
//res is now the same as above, to be honest I like the native version better :)

如果那是你的事,请下划线小提琴。

于 2013-07-29T13:44:07.293 回答
3

首先,这将它们分组而不使用参数(只是创建每个具有相同值的新数组),然后按结果数组长度对它们进行排序。然后使用前三个和后三个元素创建两个新的 min 和 max 数组。 .map用于仅返回第一个元素而不是由 . 创建的数组.groupBy

编辑:这是 Benjamin Gruenbaum 对我的原始答案的巧妙编辑。

var arr = [1,1,1,1,1,1,2,3,4,5,6,7,7,8,9,10,9,8,9,8];
var group = _.sortBy(_.groupBy(arr), "length");
var min = _.pluck(group.slice(0, 3),0);
var max = _.pluck(group.slice(-3),0);
console.log(min);
console.log(max);

jsFiddle

于 2013-07-29T13:57:05.527 回答