目次
概要
配列の中から「レベル50以上のキャラクター」や「スコア80点以上の合格者」など、特定の基準を満たすデータだけを抽出して新しいリストを作成したい場合、filter メソッドが最適です。
for 文や if 文を組み合わせるよりも簡潔に記述でき、元の配列を変更せずに新しい配列を生成する(非破壊的)ため、バグの少ない安全なコードを書くことができます。本記事では、ゲームのギルドメンバーをレベル別に選抜する機能を例に解説します。
仕様(入出力)
filter メソッド
配列の全要素に対してテスト関数を実行し、結果が true となった要素だけを集めて新しい配列を返します。
| 引数・戻り値 | 説明 |
callbackFn | 各要素をテストする関数。(element, index, array) => 真偽値 |
| 戻り値 | テストに合格した要素からなる 新しい配列。 1つも合格しなかった場合は 空の配列 [] を返します。 |
- 入力: 元の配列
- 出力: 抽出された新しい配列
- 特徴: 元の配列の要素数は変わりません。
基本の使い方
1. 数値を条件で絞り込む
アロー関数を使うと1行で記述できます。
const scores = [45, 90, 30, 85, 60];
// 80点以上だけを抽出
const highScores = scores.filter(score => score >= 80);
console.log(highScores); // [90, 85]
2. コードブロックを使う場合(returnが必要)
処理が複数行になる場合は {} で囲み、明示的に return を記述します。
const numbers = [1, 2, 3, 4, 5, 6];
const oddNumbers = numbers.filter(num => {
// 奇数かどうかを判定
return num % 2 !== 0;
});
console.log(oddNumbers); // [1, 3, 5]
コード全文(HTML / JavaScript)
クエストの参加条件に合わせて、ギルドメンバーの中から「指定レベル以上」のキャラクターをボタン一つで選抜するツールを作成します。
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Guild Member Selector</title>
<style>
.guild-panel {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 500px;
padding: 20px;
border: 2px solid #4a3b2c;
border-radius: 8px;
background-color: #fdf5e6;
color: #4a3b2c;
}
h3 { margin-top: 0; text-align: center; border-bottom: 2px solid #daa520; padding-bottom: 10px; }
.mission-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 20px;
}
.rank-btn {
padding: 10px 15px;
border: 1px solid #8b4513;
background-color: #fff8dc;
color: #8b4513;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
transition: all 0.2s;
}
.rank-btn:hover, .rank-btn.active {
background-color: #8b4513;
color: #fff;
}
.member-list {
list-style: none;
padding: 0;
margin: 0;
border-top: 1px solid #ccc;
}
.member-card {
padding: 10px;
border-bottom: 1px dashed #ccc;
display: flex;
justify-content: space-between;
align-items: center;
}
.level-badge {
background-color: #daa520;
color: white;
padding: 3px 8px;
border-radius: 12px;
font-size: 0.9em;
}
</style>
</head>
<body>
<div class="guild-panel">
<h3>ギルドメンバー選抜</h3>
<div class="mission-controls">
<button class="rank-btn active" data-min-level="1">全メンバー</button>
<button class="rank-btn" data-min-level="30">中級 (Lv30~)</button>
<button class="rank-btn" data-min-level="50">上級 (Lv50~)</button>
<button class="rank-btn" data-min-level="80">精鋭 (Lv80~)</button>
</div>
<ul id="party-list" class="member-list">
</ul>
<p id="party-count" style="text-align: right; font-size: 0.9em; margin-top: 10px;"></p>
</div>
<script src="guild_selector.js"></script>
</body>
</html>
JavaScript
/**
* ギルドメンバー選抜スクリプト
* filterメソッドを使用したレベル別抽出
*/
// 1. ギルドメンバーリスト(オブジェクトの配列)
// レベル(level)と名前(name)を持つデータ
const guildMembers = [
{ name: "森", level: 85 },
{ name: "小林", level: 12 },
{ name: "大木", level: 45 },
{ name: "中林", level: 60 },
{ name: "小森", level: 92 },
{ name: "林", level: 25 },
{ name: "大森", level: 55 },
{ name: "中木", level: 78 },
{ name: "小木", level: 8 },
{ name: "大林", level: 33 }
];
// DOM要素の取得
const listContainer = document.getElementById('party-list');
const countDisplay = document.getElementById('party-count');
const buttons = document.querySelectorAll('.rank-btn');
/**
* リストを描画する関数
* @param {Array} members - 表示対象のメンバー配列
*/
const renderMembers = (members) => {
listContainer.innerHTML = '';
if (members.length === 0) {
listContainer.innerHTML = '<li class="member-card">条件を満たすメンバーはいません。</li>';
countDisplay.textContent = '参加可能: 0名';
return;
}
members.forEach((member) => {
const li = document.createElement('li');
li.className = 'member-card';
li.innerHTML = `
<span class="member-name">${member.name}</span>
<span class="level-badge">Lv.${member.level}</span>
`;
listContainer.appendChild(li);
});
countDisplay.textContent = `参加可能: ${members.length}名`;
};
/**
* フィルタリング実行関数
*/
const filterByLevel = (event) => {
const clickedBtn = event.target;
// 1. ボタンのステータス更新
buttons.forEach(btn => btn.classList.remove('active'));
clickedBtn.classList.add('active');
// 2. data属性から必要レベルを取得
const requiredLevel = Number(clickedBtn.dataset.minLevel);
// 3. filterメソッドで抽出
// メンバーのレベルが必要レベル以上かどうかを判定
const selectedMembers = guildMembers.filter((member) => {
return member.level >= requiredLevel;
});
// 4. 結果を描画
renderMembers(selectedMembers);
};
// 初期表示(全員)
renderMembers(guildMembers);
// イベントリスナーの設定
buttons.forEach((btn) => {
btn.addEventListener('click', filterByLevel);
});
カスタムポイント
- 範囲指定の追加:「レベル30以上、かつ50未満」のような中間層を抽出したい場合は、条件式を拡張します。JavaScript
list.filter(member => member.level >= 30 && member.level < 50); - 除外設定:特定のメンバー(例: “森”)を除外したい場合は、否定演算子
!を使用します。JavaScriptlist.filter(member => member.name !== '森');
注意点
- 該当なしの挙動
findメソッドとは異なり、条件に一致する要素が1つもない場合でもundefinedにはならず、空の配列[]が返されます。データの有無を確認する際はresult.lengthをチェックしてください。 - 破壊的ではない
filterは元の配列(guildMembers)を変更しません。フィルタリング結果は必ず新しい変数で受け取る必要があります。
応用
有効なデータのみをクレンジングする
配列の中に null や undefined、あるいは無効なステータスのデータが混ざっている場合、それらを取り除く用途でも活躍します。
const rawData = [100, null, 200, undefined, 0, 300];
// 値が存在するもの(null/undefined以外)だけを残す
const validData = rawData.filter(val => val != null);
console.log(validData); // [100, 200, 0, 300]
まとめ
filter メソッドは、大量のデータから必要なものだけを「ふるい」にかけるための強力なツールです。
- 抽出: 条件に合うデータをすべて集める。
- 削除: 条件に合うデータを除外した新しい配列を作る(削除の代用)。
- 非破壊: 元のデータはそのまま残る。
この3つの特徴を理解し、データの検索や絞り込み機能に活用してください。
