LoginSignup
0
0

More than 1 year has passed since last update.

【JavaScript】reduce()で配列から指定した値の近似値を取得する

Posted at

海外のブログで、配列から指定した値の近似値を取得する方法が紹介されていたのでメモ。いったん配列をソートしてから近似値を求めるより、reduce() を使った方が早いらしい。

参考: JFind the closest number in an array JavaScript

配列内で "8" に一番近い値を取得する

const needle = 8;

const closest = [1, 10, 7, 2, 4, 9].reduce((a, b) => {
    return Math.abs(b - needle) < Math.abs(a - needle) ? b : a;
});

console.log(closest); // 出力値: 7

この方法だと結果は "7" になる。配列に "9" があったとしても、先に比較された "7" が最近似値となる。

これだと問題となるケースがあるため、「大きい方 vs 小さいほう (> vs <)」を指定して、どちらを近似値とするかを決められるようにする。

const needle = 8;

const closest = [1, 10, 7, 2, 4, 9].reduce((a, b) => {
    let aDiff = Math.abs(a - needle);
    let bDiff = Math.abs(b - needle);

    if (aDiff == bDiff) {
        // 大きい方 vs 小さいほう (> vs <) を指定する
        return a > b ? a : b;
    } else {
        return bDiff < aDiff ? b : a;
    }
});

console.log(closest); // 出力値: 9

使い回しができるよう関数化する

function getClosestNum(needle, haystack) {
    return haystack.reduce((a, b) => {
        let aDiff = Math.abs(a - needle);
        let bDiff = Math.abs(b - needle);

        if (aDiff == bDiff) {
            // 大きい方 vs 小さいほう (> vs <) を指定する
            return a > b ? a : b;
        } else {
            return bDiff < aDiff ? b : a;
        }
    });
}

ざっと動作確認してみる。

// 数値のみの配列
const needle = 8;
const numbers = [1, 52, 0, -25, 10, 7, 2, -128, 4, 9, 99, 256];

let closetnum = getClosestNum(needle, numbers);
console.log(closetnum);  // 出力値: 9
// いろいろごちゃまぜの配列
const needle = 0.5940;
const numbers = [1, 10, NaN, 7, -5, null, "テスト", 2, 4, 9, "Test", 0.5267, 0.5877, NaN, 0.6534, NaN];
let closetnum = getClosestNum(needle, numbers);
console.log(closetnum);// 出力値: 0.5877

いろいろごちゃまぜの配列にしても、近似値を取得できているが、あまり無茶をするとバグりそう(汗

参考:

JFind the closest number in an array JavaScript
JavaScript 配列から指定した値の近似値を取得
【javascript】reduce

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0