【JavaScript】配列から偶数番目・奇数番目の要素を取得する方法|filter・for ループ・reduce・n 番おき・テーブル交互行まで解説

テーブルの交互行に背景色を付ける、配列を 2 列に分割してレイアウトする、データを 1 つおきに間引くなど、配列の偶数番目・奇数番目の要素を取得する操作は実務で意外と出番があります。この記事では filter / for ループ / reduce の 3 つのアプローチに加え、n 番おきの汎用パターンまで解説します。

この記事でわかること
・filter でインデックスの偶奇を判定する方法
・for ループで偶奇を同時に分類する方法
・reduce で 1 回のループで偶奇を分離する方法
・0 始まりと 1 始まりの違い
・n 番おきの要素を取得する汎用関数
・テーブルの交互行スタイル・2 列レイアウト・ペアワイズ処理の実務パターン
スポンサーリンク

インデックスの偶奇と「何番目」の関係

JavaScript の配列インデックスは 0 始まりのため、「偶数インデックス」と「偶数番目」が一致しない点に注意が必要です。

要素 A B C D E
インデックス 0 1 2 3 4
インデックスの偶奇 偶数 奇数 偶数 奇数 偶数
何番目(1始まり) 1番目 2番目 3番目 4番目 5番目

つまり index % 2 === 01 番目・3 番目・5 番目(1 始まりの奇数番目)の要素を取得します。ここでは「偶数インデックス」「奇数インデックス」の表現で統一します。

filter でインデックスの偶奇を判定する(推奨)

JavaScript
const arr = ["A", "B", "C", "D", "E", "F"];

// 偶数インデックス: 0, 2, 4 → A, C, E
const evens = arr.filter((_, i) => i % 2 === 0);
console.log(evens); // ["A", "C", "E"]

// 奇数インデックス: 1, 3, 5 → B, D, F
const odds = arr.filter((_, i) => i % 2 !== 0);
console.log(odds);  // ["B", "D", "F"]
filter は元の配列を変更せず、条件に合う要素の新しい配列を返します。1 行で書けて読みやすいため、最も推奨される方法です。

for ループで偶奇を同時に分類する

JavaScript
const arr = ["A", "B", "C", "D", "E", "F"];
const evens = [];
const odds = [];

for (let i = 0; i < arr.length; i++) {
  if (i % 2 === 0) {
    evens.push(arr[i]);
  } else {
    odds.push(arr[i]);
  }
}

console.log(evens); // ["A", "C", "E"]
console.log(odds);  // ["B", "D", "F"]

filter を 2 回呼ぶと配列を 2 周しますが、for ループなら1 周で偶奇を同時に分類できます。パフォーマンスを重視する場合に有効です。

ステップ付きループで偶数インデックスだけ処理する

JavaScript
const arr = ["A", "B", "C", "D", "E", "F"];
const evens = [];

// i += 2 で2つ飛ばし
for (let i = 0; i < arr.length; i += 2) {
  evens.push(arr[i]);
}

console.log(evens); // ["A", "C", "E"]
ステップ付きループ(i += 2)は filter より高速ですが、偶奇のどちらかだけが必要な場合に限ります。両方同時に必要なら for + if/else が効率的です。

reduce で 1 回のループで偶奇を分離する

JavaScript
const arr = ["A", "B", "C", "D", "E", "F"];

const { evens, odds } = arr.reduce(
  (acc, val, i) => {
    if (i % 2 === 0) {
      acc.evens.push(val);
    } else {
      acc.odds.push(val);
    }
    return acc;
  },
  { evens: [], odds: [] }
);

console.log(evens); // ["A", "C", "E"]
console.log(odds);  // ["B", "D", "F"]

方法の比較

方法 周回数 偶奇同時取得 コードの簡潔さ
filter × 2 2 周 ★★★ 簡潔
for + if/else 1 周 ★★
reduce 1 周 ★★
ステップ付き for 約 0.5 周 ×(片方のみ) ★★★

n 番おきの要素を取得する汎用関数

偶奇だけでなく「3 番おき」「5 番おき」にも対応する汎用パターンです。

JavaScript
function everyNth(arr, n, offset = 0) {
  return arr.filter((_, i) => (i - offset) % n === 0);
}

const arr = ["A", "B", "C", "D", "E", "F", "G", "H", "I"];

// 3番おき(インデックス 0, 3, 6)
console.log(everyNth(arr, 3));    // ["A", "D", "G"]

// 3番おき(インデックス 1, 4, 7 から開始)
console.log(everyNth(arr, 3, 1)); // ["B", "E", "H"]

// 2番おき = 偶数インデックス
console.log(everyNth(arr, 2));    // ["A", "C", "E", "G", "I"]

配列を n 個ずつのグループに分割する

JavaScript
function chunk(arr, size) {
  const result = [];
  for (let i = 0; i < arr.length; i += size) {
    result.push(arr.slice(i, i + size));
  }
  return result;
}

console.log(chunk(["A", "B", "C", "D", "E"], 2));
// [["A", "B"], ["C", "D"], ["E"]]

実務でよく使うパターン

テーブルの交互行にスタイルを適用する

CSS だけで対応(推奨)
/* CSS の :nth-child で交互行を設定 */
table tr:nth-child(even) {
  background-color: #f8fafc;
}
table tr:nth-child(odd) {
  background-color: #fff;
}
JavaScript で動的に適用する場合
const rows = document.querySelectorAll("#myTable tbody tr");

rows.forEach((row, i) => {
  row.style.backgroundColor = i % 2 === 0 ? "#fff" : "#f8fafc";
});
テーブルの交互行スタイルは CSS の :nth-child(even / odd) だけで実現できます。JavaScript は行のフィルタリングや動的追加時など、CSS だけでは対応できない場合に使いましょう。

配列を 2 列に分割してレイアウトする

JavaScript
const items = ["商品A", "商品B", "商品C", "商品D", "商品E"];

// 偶数インデックス → 左列、奇数インデックス → 右列
const leftColumn = items.filter((_, i) => i % 2 === 0);
const rightColumn = items.filter((_, i) => i % 2 !== 0);

console.log(leftColumn);  // ["商品A", "商品C", "商品E"]
console.log(rightColumn); // ["商品B", "商品D"]

ペアワイズ処理(隣接する 2 要素をペアにする)

JavaScript
function pairwise(arr) {
  const pairs = [];
  for (let i = 0; i < arr.length; i += 2) {
    pairs.push([arr[i], arr[i + 1]]);
  }
  return pairs;
}

// [キー, 値] のペアに変換
const flat = ["name", "田中", "age", "30", "city", "東京"];
const pairs = pairwise(flat);
console.log(pairs);
// [["name", "田中"], ["age", "30"], ["city", "東京"]]

// オブジェクトに変換
const obj = Object.fromEntries(pairs);
console.log(obj);
// { name: "田中", age: "30", city: "東京" }

データの間引き(サンプリング)

JavaScript
// センサーデータなど大量のデータを n 番おきに間引く
const sensorData = Array.from({ length: 1000 }, (_, i) => ({
  time: i,
  value: Math.random() * 100
}));

// 10番おきにサンプリング(1000件 → 100件)
const sampled = sensorData.filter((_, i) => i % 10 === 0);
console.log(sampled.length); // 100

関連記事

よくある質問

Qindex % 2 === 0 は「偶数番目」ですか「奇数番目」ですか?
AJavaScript のインデックスは 0 始まりのため、index % 2 === 0 はインデックス 0, 2, 4 の要素、つまり1 番目、3 番目、5 番目(1 始まりの奇数番目)です。混乱を避けるため「偶数インデックス」「奇数インデックス」と表現するのが正確です。
Qfilter を 2 回呼ぶのはパフォーマンス的に問題ありますか?
A通常の配列サイズ(数千件程度)であれば体感差はありません。数万件以上で気になる場合は、for ループや reduce で 1 回のループで偶奇を同時に分類してください。
Qn 番おき(3 つおきなど)の要素を取得するには?
Aarr.filter((_, i) => i % n === 0) で n 番おきの要素を取得できます。開始位置をずらしたい場合は (i - offset) % n === 0 とします。
Qテーブルの交互行は CSS と JavaScript のどちらで実装すべきですか?
ACSS の tr:nth-child(even) だけで実現できるため、CSS が推奨です。JavaScript は動的に行を追加・フィルタリングする場合など、CSS だけでは対応できない場面で使います。
Q隣接する 2 要素をペアにするにはどうすればよいですか?
Afor ループで i += 2 とステップし、[arr[i], arr[i + 1]] をペアとして配列に追加します。結果を Object.fromEntries() に渡せばオブジェクトに変換できます。

まとめ

配列から偶数番目・奇数番目の要素を取得する方法を整理しました。

  • filter: arr.filter((_, i) => i % 2 === 0)(シンプル・推奨)
  • for ループ: 1 回のループで偶奇を同時に分類(パフォーマンス重視)
  • reduce: 1 回のループで偶奇をオブジェクトにまとめる
  • ステップ付きループ: i += 2 で片方だけ高速に取得
  • n 番おき: i % n === 0 で汎用的にサンプリング

テーブル交互行は CSS :nth-child(even/odd) が最適、2 列レイアウトやデータの間引きには filter、ペアワイズ処理にはステップ付き for ループと使い分けてください。