arrBinarySearch.mjs

import get from 'lodash-es/get.js'
import size from 'lodash-es/size.js'
import map from 'lodash-es/map.js'
import filter from 'lodash-es/filter.js'
import sortBy from 'lodash-es/sortBy.js'
import isearr from 'wsemi/src/isearr.mjs'
import isnum from 'wsemi/src/isnum.mjs'
import isbol from 'wsemi/src/isbol.mjs'
import cdbl from 'wsemi/src/cdbl.mjs'


/**
 * 陣列二分搜尋法
 *
 * Unit Test: {@link https://github.com/yuda-lyu/w-optimization/blob/master/test/arrBinarySearch.test.js Github}
 * @memberOf w-optimization
 * @param {Array} arr 輸入數據陣列
 * @param {Number} x 輸入尋找數字
 * @param {Object} [opt={}] 輸入設定物件,預設{}
 * @param {Boolean} [opt.sorted=false] 輸入陣列arr是否已經排序,若陣列已排序可加快速度,預設為false
 * @returns {Object} 回傳求解後結果物件,含鍵值x,y,x為求解後變數組,y為最優適應函數值
 * @example
 *
 * let arr = [1, 2, 4, 6, 1, 100, 0, 10000, 3]
 *
 * console.log(arrBinarySearch(arr, 2))
 * // => { ind: 1, indSorted: 3, value: 2 }
 *
 * console.log(arrBinarySearch(arr, 5))
 * // => null
 *
 */
function arrBinarySearch(arr, x, opt = {}) {

    //check
    if (!isearr(arr)) {
        return null
    }

    //sorted
    let sorted = get(opt, 'sorted')
    if (!isbol(sorted)) {
        sorted = false
    }

    //filter
    arr = filter(arr, isnum)

    //cdbl
    arr = map(arr, cdbl)

    //轉成物件陣列
    arr = map(arr, (v, k) => {
        return { v, k }
    })

    //sortBy
    if (!sorted) {
        arr = sortBy(arr, 'v')
        // console.log('arr', arr)
    }

    //search
    let iStart = 0
    let iEnd = size(arr) - 1
    while (iStart <= iEnd) {

        //iMid
        let iMid = Math.floor((iStart + iEnd) / 2)
        // console.log(iMid, arr[iMid])

        //checj
        if (arr[iMid].v === x) {
            return {
                ind: arr[iMid].k,
                indSorted: iMid,
                value: x,
                // diff: 0,
            }
        }

        if (x < arr[iMid].v) {
            iEnd = iMid - 1
        }
        else {
            iStart = iMid + 1
        }
    }

    return null
}


export default arrBinarySearch