配列のデータを一定間隔で間引く方法

配列のデータ数が多すぎる場合に、一定の間隔で間引き、データの数を減らした配列を作る方法を紹介します。

配列のデータ数 i を間引き数 step で剰余演算し、結果が0(余りが無し)ならば、新しい配列に挿入するという動作を行います。ここでは、もう一ひねりして、削減後の目標データ数 thinNum を与えて、間引き数  step も計算させてみます。

Node-REDのフローは以下の様になります。

injectノードとfunctionノード2つとデバッグノードで構成されています。主要ノードは「thin out」のfunctionノードです。
「準備」のノードは、配列が格納されているflow変数dataから配列を読み込んでmsg.payloadに流しているだけです。もともと配列が、msg.payloadに乗ってくるのであれば不要なノードです。

「準備」のfunctionノード

msg.payload = flow.get("data");
return msg;

ここでは、削減後のデータ目標数 thinNum を10,000としています。間引き数の計算では、配列のデータ総数 data.length を目標数 thinNum で割り、四捨五入をして間引き数 step を求めています。間引き数 step が1より小さい場合は、間引き数 step を1にして間引かないようにします。

間引き処理は、配列をデータ数 i を間引き数 step で剰余演算し、余りが0なら、新しい配列 new_data に挿入(push)しています。余りがある場合にはデータを捨てます。

最後に新しい配列 new_data をmsg.payloadに代入して、returnでmsgを返します。

// 準備
var i = 0;             // カウンタ
var new_data =[];      // 新しい配列
var thinNum = 10000;   // 削減後データ目標数 

// 配列取込
var data = msg.payload;

// 間引き数を計算
var step = Math.round(data.length / thinNum);
if (step < 1){    // 間引き数が1より小さい場合は
    step = 1;     // 間引かない
}

// 間引き処理
for (i=0; i<data.length; i++){
    if (i % step == 0){         // 剰余演算
        new_data.push(data[i]); // 間引き配列へ挿入
    }
}
// 間引き配列をmsg.payloadに代入
msg.payload = new_data;  

// デバッグ用
msg.i = i;
msg.thinNum;
msg.step = step;
return msg;

試行結果を次に示します。

msg.payloadの配列数が9,839です。それに対して元の配列のデータ数 i が49,194です。間引き数step は、 49,194 ÷ 10,000 = 4.9194 を四捨五入した 5 になっています。目標データ数の10,000に間引かれていることが分かります。