3

これにはアンダースコアを使用したいのですが、何らかのばかげた理由でそれは私を逃れます:

数字のリストがあります: 39、39、10、1、3、4、5... など

最も頻度の高い 3 つと頻度の低い 3 つを返したいと思います。

_.countBy を使用してみましたが、どうにかしてオブジェクトを返すため、おそらく明らかなものを見逃していない限り、並べ替えが困難 (?) になります。

4

2 に答える 2

9

私をクレイジーと呼んでください、しかしこれはアンダースコアのない解決策O(n log n)です.最大3つを検索する代わりにソートするため、特に高速ではありません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

最初に、これはパラメーターなしでそれらをグループ化し (それぞれが同じ値を持つ新しい配列を作成するだけです)、次にそれらを結果の配列の長さで並べ替えます。次に、最初の 3 つの要素と最後の 3 つの要素を使用して、最小値と最大値の 2 つの新しい配列を作成します。 .mapによって作成された配列ではなく、最初の要素のみを返すために使用され.groupByます。

EDIT : これは、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);

jsフィドル

于 2013-07-29T13:57:05.527 に答える