JavaScriptで実装するRubyのeach_cons()メソッド
Rubyのeach_cons()メソッドとは
Rubyのeach_cons()は、Enumerableモジュールに組み込まれたメソッドの一つです。各要素を起点として、連続するN個の要素を順番に取り出しながら繰り返し処理を行います。ブロックを渡さなかった場合には、Enumeratorを返します。
JavaScriptにおけるeachCons()相当の実装
ここでは、数値の配列(このケースではRubyのEnumerableに相当するもの)を例に考えてみましょう。eachCons関数は、配列の各要素に対して実行され、引数として数値N(Nは配列の長さ以下)を1つだけ受け取るArrayの関数である必要があります。そして、サイズNの部分配列を要素とする新しい配列を返します。各部分配列は、元の配列の要素を先頭から順に1つずつ起点としたものになります。
具体的な例を見た方が理解しやすいでしょう。
次のような配列があるとします。
const arr = [1, 2, 3, 4, 5]; console.log(arr.eachCons(2));
このeachConsの呼び出しは、2つの要素を持つ部分配列からなる配列を以下のように生成します。
[[1, 2], [2, 3], [3, 4], [4, 5]]
注目すべきは、元の配列の各要素を起点として、作成できる範囲で部分配列が生成されているという点です。
Nの値が2ではなく3だった場合、結果は次のようになります。
[[1, 2, 3], [2, 3, 4], [3, 4, 5]]
この場合も、配列内に十分な要素がなくなるまで、各要素を起点として部分配列が作成されます。
実装アプローチ:スライディングウィンドウ
この問題は、スライディングウィンドウ(滑動窓)アルゴリズムを使って解決します。
モダンなES6の関数を活用すれば2行程度で書くこともできますが、ここで紹介するアプローチの方がはるかに効率的です。
まず、whileループを使って0番目からN番目のインデックスまでの初期ウィンドウを作成します。その後、ウィンドウの末尾が元の配列の長さより小さい間、forループを実行します。
このループでは、ウィンドウの安定性(ウィンドウの長さがNと等しいかどうか)をチェックします。ウィンドウが安定している場合は、そのウィンドウ(部分配列)を結果配列に挿入し、ウィンドウを右へ1つスライドさせて畳みます(start = end)。ウィンドウが不安定な場合は、要素を追加し続けます。
コード例
const arr = [1, 2, 3, 4, 5];
const eachCons = function(num){
let res = [], temp = [];
let start = 0, end = 0;
while(end < num){
temp.push(this[end++]);
};
for(; end <= this.length ;){
if(temp.length === num){
res.push(temp);
start++;
end = start;
temp = [];
}
temp[end-start] = this[end];
end++;
}
return res;
};
Array.prototype.eachCons = eachCons;
console.log([1, 2, 3, 4, 5].eachCons(1));
console.log([1, 2, 3, 4, 5].eachCons(2));
console.log([1, 2, 3, 4, 5].eachCons(3));
console.log([1, 2, 3, 4, 5].eachCons(4));
出力結果
コンソールには以下のように出力されます。
[ [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ] ] [ [ 1, 2 ], [ 2, 3 ], [ 3, 4 ], [ 4, 5 ] ] [ [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ] ] [ [ 1, 2, 3, 4 ], [ 2, 3, 4, 5 ] ]
-
【JavaScript入門】Symbolを使ってオブジェクトごとに一意のIDを作成する方法
はじめにJavaScriptでオブジェクトごとに一意のIDを作成したい場合、Symbol()を使うのが最も簡単かつ確実な方法です。Symbolは呼び出されるたびに必ず新しい一意の値を生成するため、たとえ同じ説明文字列を渡しても、二度と同じ値にはなりません。以下は、各オブジェクトに対して一意のIDを作成するサンプルコードです。実装例<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewp
-
JavaScriptで連結リストの各ノードの「次に大きい値」を効率的に求める方法
問題概要JavaScriptで、連結リストの先頭ノード(head)を唯一の引数として受け取る関数を作成することを考えます。この連結リストには数値データが格納されており、リスト内の各ノードには「次に大きい値(next larger value)」が存在する場合があります。ノードiに対して next_larger(node_i) とは、j > i かつ node_j.val > node_i.val を満たすノードの中で、j が最小になるような node_j.val のことです。そのような j が存在しない場合、次に大きい値は 0 となります。つまり私たちの関数は、リスト内の各要素に対