JavaScriptで配列内の唯一異なる要素(仲間はずれ)を見つける方法
今回は、すべて同じ値で構成されており、ただ一つだけ異なる要素が混ざっている配列を受け取り、その「仲間はずれ」の値を返すJavaScript関数を作成していきます。
例えば [2, 4, 4, 4, 4] のような配列が渡された場合、関数は 2 を返す必要があります。それでは、実際のコードを見ていきましょう。
実装例
配列の長さは少なくとも3以上であることを前提とし、隣接する要素同士を比較しながらループ処理を行う方法です。
const arr = [2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4];
// 配列の長さは最低でも3であることを前提とする
const findUnlike = arr => {
for (let i = 1; i < arr.length - 1; i++) {
// 前の要素と異なり、次の要素とも異なる場合は現在の要素が仲間はずれ
if (arr[i] - arr[i - 1] !== 0 && arr[i] - arr[i + 1] !== 0) {
return arr[i];
}
// 現在の要素と前の要素が異なり、次の要素とは一致する場合、前の要素が仲間はずれ
else if (arr[i] - arr[i - 1] !== 0 && arr[i] - arr[i + 1] === 0) {
return arr[i - 1];
}
// 現在の要素と前の要素が一致し、次の要素と異なる場合、次の要素が仲間はずれ
else if (arr[i] - arr[i - 1] === 0 && arr[i] - arr[i + 1] !== 0) {
return arr[i + 1];
}
}
};
console.log(findUnlike(arr));
出力結果
コンソールには以下のように出力されます。
2
コードの解説
この関数は、配列の先頭から順に隣接する3つの要素を比較していく仕組みです。ほとんどの要素は同じ値で占められているため、値が切り替わる境界部分に到達した時点で、どちら側が少数派かを判定できます。
- 両隣と一致しない場合:現在の要素自身が仲間はずれです。
- 前だけ異なり後ろと一致する場合:前の要素が仲間はずれです(配列の先頭が異なるケース)。
- 前と一致し後ろだけ異なる場合:次の要素が仲間はずれです(配列の末尾が異なるケース)。
なお、元のコードでは最初の条件分岐が誤って重複していたため、正しく動作するように条件を整理しています。
よりシンプルな別のアプローチ
隣接比較を使わず、indexOf() と lastIndexOf() を組み合わせれば、より簡潔に記述することも可能です。「最初に出現する位置」と「最後に出現する位置」が同じ要素は配列内に1回しか現れない、つまり仲間はずれだという性質を利用しています。
const findUnlike = arr => arr.find((v, i) => arr.indexOf(v) === i && arr.lastIndexOf(v) === i); console.log(findUnlike([2, 4, 4, 4, 4])); // 2
この方法なら、異なる要素が配列のどの位置にあっても(先頭・中央・末尾問わず)確実に検出できるのがメリットです。
まとめ
「ほぼ同一の値の中に一つだけ異なる要素がある」という問題は、隣接要素の比較でもフィルタリングでも解決できます。データの特性(要素数やパフォーマンス要件)に応じて、適切な実装を選びましょう。
-
JavaScriptのlastIndexプロパティの使い方を解説!正規表現のマッチ位置を取得する方法
JavaScriptのlastIndexプロパティとは JavaScriptのlastIndexプロパティは、正規表現によるマッチが発生したインデックス位置(文字位置)を返すプロパティです。このプロパティを利用すると、次回のマッチ検索はその位置から再開されます。 重要なポイントとして、lastIndexプロパティが機能するのは、正規表現に「g」(グローバル)フラグが設定されている場合のみです。「g」フラグがない場合、lastIndexは常に0のまま変化しません。 lastIndexプロパティの主な特徴 マッチが見つかった位置の次のインデックスを記録します test()メソッドやexec()メ
-
JavaScriptで特定の文字列の順序に従って文字列を並べ替える方法
問題 2つの文字列 str1 と str2 を第1・第2引数として受け取るJavaScript関数を作成する必要があります。 この関数は、str1 を str2 に含まれる文字の出現順序に従って並べ替えます。 例えば、関数への入力が以下の場合を考えてみましょう。 入力 const str1 = coding; const str2 = gncabdi; 出力 const output = gncdio; 出力の説明 str2 の中で先に現れる文字が優先的に前に配置され、その後に後から現れる文字が続きます。そして最後に、str2 に存在しない残りの文字がそのまま並べられます。 解決のアプローチ