テーブルの交互行に背景色を付ける、配列を 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 === 0 は1 番目・3 番目・5 番目(1 始まりの奇数番目)の要素を取得します。ここでは「偶数インデックス」「奇数インデックス」の表現で統一します。
filter でインデックスの偶奇を判定する(推奨)
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"]
for ループで偶奇を同時に分類する
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 周で偶奇を同時に分類できます。パフォーマンスを重視する場合に有効です。
ステップ付きループで偶数インデックスだけ処理する
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 回のループで偶奇を分離する
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 番おき」にも対応する汎用パターンです。
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 個ずつのグループに分割する
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 の :nth-child で交互行を設定 */
table tr:nth-child(even) {
background-color: #f8fafc;
}
table tr:nth-child(odd) {
background-color: #fff;
}
const rows = document.querySelectorAll("#myTable tbody tr");
rows.forEach((row, i) => {
row.style.backgroundColor = i % 2 === 0 ? "#fff" : "#f8fafc";
});
:nth-child(even / odd) だけで実現できます。JavaScript は行のフィルタリングや動的追加時など、CSS だけでは対応できない場合に使いましょう。配列を 2 列に分割してレイアウトする
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 要素をペアにする)
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: "東京" }
データの間引き(サンプリング)
// センサーデータなど大量のデータを 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
関連記事
- 配列の使い方まとめ — 作成・追加・削除・ループ・スプレッド構文
- 配列の map・filter・reduce の使い方
- 配列の最初と最後の要素を判定する方法
- n 番目以外の子要素を取得する方法
- slice の使い方 — 配列の切り出し
よくある質問
index % 2 === 0 はインデックス 0, 2, 4 の要素、つまり1 番目、3 番目、5 番目(1 始まりの奇数番目)です。混乱を避けるため「偶数インデックス」「奇数インデックス」と表現するのが正確です。arr.filter((_, i) => i % n === 0) で n 番おきの要素を取得できます。開始位置をずらしたい場合は (i - offset) % n === 0 とします。tr:nth-child(even) だけで実現できるため、CSS が推奨です。JavaScript は動的に行を追加・フィルタリングする場合など、CSS だけでは対応できない場面で使います。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 ループと使い分けてください。