JavaScript 逆引き集 | findIndex でインデックス取得

JavaScript JavaScript
スポンサーリンク

JavaScript配列のインデックス取得(findIndex)の基本と実践

「条件に合う要素が配列のどこにあるか」を知りたいなら findIndex。見つかった最初の位置(インデックス)を返し、見つからなければ -1。インデックスが分かれば、更新・削除・挿入などの操作に一気に応用できます。


構文と考え方

const index = arr.findIndex((value, index, array) => {
  // 条件式(true/false)を返す
  return /* 条件式 */;
});
JavaScript
  • 返り値: 条件に合う「最初の要素のインデックス」。見つからなければ -1
  • 引数: コールバックには最大3つ(value, index, array)が渡される。ログやデバッグ、複合条件に便利。
  • 特徴: 最初の一致で検索終了。複数一致があっても、返るのは先頭の1件の位置。

すぐ使えるテンプレート集

基本:id が 3 の要素のインデックスを取得

const items = [
  { id: 1, name: "Pen" },
  { id: 2, name: "Note" },
  { id: 3, name: "Bag" },
  { id: 3, name: "Shoes" },
];

const i = items.findIndex(x => x.id === 3);
console.log(i); // 2(最初の {id:3} の位置)
JavaScript
  • ポイント: 2つ目以降の一致は無視される。最初の一致だけ。

見つからない場合の安全な扱い

const nums = [1, 2, 3];
const i = nums.findIndex(n => n > 10);

if (i === -1) {
  console.log("見つかりませんでした");
} else {
  console.log("位置:", i, "値:", nums[i]);
}
JavaScript
  • ポイント: -1 チェックは必須。-1 をそのまま参照すると最後の要素を誤って触るコードが出がち。

見つかった位置の要素を更新

const products = [
  { id: 1, price: 120 },
  { id: 2, price: 300 },
  { id: 3, price: 450 },
];

const i = products.findIndex(p => p.id === 2);
if (i !== -1) {
  products[i] = { ...products[i], price: 330 }; // 値上げ
}
console.log(products);
JavaScript
  • ポイント: スプレッドで安全に「上書き」。不変性を保ちたい場合は新配列を作る。

見つかった位置の要素を削除(splice)

const cart = [
  { id: 1, name: "Pen" },
  { id: 2, name: "Note" },
  { id: 3, name: "Bag" },
];

const i = cart.findIndex(x => x.id === 2);
if (i !== -1) {
  cart.splice(i, 1); // その位置から1件削除
}
console.log(cart);
JavaScript
  • ポイント: splice は元配列を変更する(破壊的)。不変にしたいなら filter を使って新配列を作る。

見つかった位置の前に挿入

const arr = ["A", "B", "D"];
const i = arr.findIndex(x => x === "D");
if (i !== -1) {
  arr.splice(i, 0, "C"); // D の前に C を挿入
}
console.log(arr); // ["A", "B", "C", "D"]
JavaScript
  • ポイント: splice の第2引数が 0 なら「削除なしで挿入」。

よくある落とし穴と対策

  • -1 チェック忘れ
    • 症状: 見つからないのに arr[-1] を参照し、思わぬバグに。
    • 対策: 必ず if (i === -1) return; などで早期リターン。
  • 破壊的操作の乱用
    • 症状: splice や直接代入で元配列が書き換わり、他所のコードに影響。
    • 対策: 不変にしたいなら、コピーしてから操作(例:slice、スプレッド、filter、map)。
  • 複数一致を想定している
    • 症状: 最初の1件しか扱えていない。
    • 対策: 全件必要なら filter を使う。findIndex は「最初の位置」専用。

現場で効くパターン集

不変で「更新した新配列」を返す

function updateById(items, id, patch) {
  const i = items.findIndex(x => x.id === id);
  if (i === -1) return items; // 変更なしで返す
  return [
    ...items.slice(0, i),
    { ...items[i], ...patch },
    ...items.slice(i + 1),
  ];
}
JavaScript
  • ポイント: 元配列を壊さず差し替え。UIフレームワークで差分検出しやすい。

不変で「削除した新配列」を返す

function removeById(items, id) {
  const i = items.findIndex(x => x.id === id);
  if (i === -1) return items;
  return [...items.slice(0, i), ...items.slice(i + 1)];
}
JavaScript
  • ポイント: filter の方が読みやすい場合もあるが、findIndex は「位置指定」が明確。

条件に応じて「前後に挿入」

function insertBefore(items, predicate, value) {
  const i = items.findIndex(predicate);
  if (i === -1) return items;
  return [...items.slice(0, i), value, ...items.slice(i)];
}
JavaScript
  • ポイント: predicate を渡せるようにすると再利用性が上がる。

練習問題(手を動かして覚える)

1. 最初の偶数のインデックスを取得

const nums = [3, 7, 11, 12, 5];
const i = nums.findIndex(n => n % 2 === 0);
console.log(i); // 3
console.log(nums[i]); // 12
JavaScript

2. id=3 の商品を 10% 値引き(不変で返す)

const products = [
  { id: 1, price: 120 },
  { id: 2, price: 300 },
  { id: 3, price: 450 },
];

const i = products.findIndex(p => p.id === 3);
const discounted =
  i === -1
    ? products
    : [
        ...products.slice(0, i),
        { ...products[i], price: Math.round(products[i].price * 0.9) },
        ...products.slice(i + 1),
      ];

console.log(discounted);
JavaScript

3. 指定文字の直前に別文字を挿入

const chars = ["a", "b", "d"];
const i = chars.findIndex(c => c === "d");
const result = i === -1 ? chars : [...chars.slice(0, i), "c", ...chars.slice(i)];
console.log(result); // ["a", "b", "c", "d"]
JavaScript

直感的な指針

  • 位置が欲しいなら: findIndex。値が欲しいなら find。
  • 全件を扱いたいなら: filter。
  • 更新・削除・挿入と相性抜群: 見つけてから splice(破壊)か不変のスライス構築で処理する。

タイトルとURLをコピーしました