我想为此使用下划线,但出于某种愚蠢的原因,它使我无法理解:
我有一个数字列表:39、39、10、1、3、4、5...等
我想返回最频繁的 3 个和不太频繁的 3 个。
我尝试过使用 _.countBy ,但它以某种方式返回了一个对象,这使得排序变得困难(?),除非我可能错过了显而易见的事情。
我想为此使用下划线,但出于某种愚蠢的原因,它使我无法理解:
我有一个数字列表:39、39、10、1、3、4、5...等
我想返回最频繁的 3 个和不太频繁的 3 个。
我尝试过使用 _.countBy ,但它以某种方式返回了一个对象,这使得排序变得困难(?),除非我可能错过了显而易见的事情。
叫我疯了,但这是一个没有下划线的解决方案,它不是特别快,因为我排序而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 :)
首先,这将它们分组而不使用参数(只是创建每个具有相同值的新数组),然后按结果数组长度对它们进行排序。然后使用前三个和后三个元素创建两个新的 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);