JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

【JavaScript】lengthとループを使わずに配列の中央要素を取得するES6再帰関数の書き方

はじめに

本記事では、配列の length プロパティにアクセスすることなく、for 文や while 文などのループ構文も一切使わずに、配列の中央にある要素を返す関数 midElement() をJavaScriptで実装する方法を解説します。ループの代わりに再帰呼び出しを活用するのがポイントです。

実装の要件

  • 配列の length プロパティを参照しないこと
  • 組み込みのループ構文(for / while など)を使用しないこと
  • 要素数が奇数の場合は、中央の1つの要素を返す
  • 要素数が偶数の場合は、中央の2つの要素を格納した配列を返す

サンプルコード

const arr = [14, 32, 36, 42, 45, 66, 87];
const array = [13, 92, 83, 74, 55, 46, 74, 82];

const midElement = (arr, ind = 0) => {
  // インデックスが指す要素が存在する限り、自分自身を再帰呼び出し
  if (arr[ind]) {
    return midElement(arr, ++ind);
  }
  // 要素数(ind)の偶奇に応じて中央の要素を返す
  return ind % 2 !== 0
    ? [arr[(ind - 1) / 2]]
    : [arr[(ind / 2) - 1], arr[ind / 2]];
};

console.log(midElement(arr));   // [ 42 ]
console.log(midElement(array)); // [ 74, 55 ]

実行結果

コンソールには次のように出力されます。

[ 42 ]
[ 74, 55 ]

コードの仕組み

この実装の鍵となるのは再帰です。処理の流れは以下の通りです。

  1. デフォルト引数 ind = 0 を走査用のインデックスとして使用し、arr[ind] が存在する限り自身を呼び出しながら ind を1ずつ増加させます。
  2. 配列の範囲外に達すると arr[ind]undefined(falsy値)になり、再帰が停止します。このときの ind は、結果的に配列の要素数と一致します。
  3. 最後に ind の偶奇を判定します。奇数なら (ind - 1) / 2 番目の要素を、偶数なら ind / 2 - 1 番目と ind / 2 番目の2要素を配列にまとめて返します。

注意点

この実装は arr[ind] の真偽値で終了判定を行っているため、配列内に 0 や空文字列などのfalsyな値が含まれていると、そこで再帰が意図より早く終了してしまう可能性があります。より堅牢にしたい場合は、ind in arr のような存在チェックに置き換えると安全です。

まとめ

ループ構文や length プロパティを使わなくても、ES6のアロー関数と再帰を組み合わせれば、配列の中央要素を簡潔に取得できます。再帰処理の考え方を身につける練習題材としてもおすすめのコードです。

  1. JavaScriptで「+」「-」「*」「/」を使わずに2つの数値の合計を求める方法

    JavaScriptで、2つの数値 m と n を引数として受け取る関数 add() を作成する必要があります。この関数は、四則演算(加算・減算・乗算・除算)を使用せずに入力された2つの数値を加算し、その合計を返すものです。 実装例 実際のコードは以下のようになります。 const m = 67, n = 33; const add = (x, y) => { while(y !== 0){ let carry = x & y; x = x ^ y; y = carry << 1; }; retu

  2. C#で組み込み関数を使わずに配列内の欠損している数と重複している数を見つける方法

    欠損している数を見つける方法まず、元の配列よりも1つ大きいサイズのbool型配列を新しく作成します。次に、元の配列全体を走査し、各数値が出現したら新しく作成した配列の対応するインデックスを true に設定していきます。すべての走査が完了した後、この配列を先頭から再度走査し、最初に false となっているインデックスが欠損している数となります。重複している数を見つける方法同様に、int型のカウント用配列を別途用意します。各数値の出現状況を記録し、同じ数が2回目に出現した時点でその位置の値を2に更新します。走査後、最初に値が2になっているインデックスが、重複している数を示します。サンプルコード