bin.mjs

import get from 'lodash-es/get.js'
import map from 'lodash-es/map.js'
import min from 'lodash-es/min.js'
import max from 'lodash-es/max.js'
import size from 'lodash-es/size.js'
import cint from 'wsemi/src/cint.mjs'
import cdbl from 'wsemi/src/cdbl.mjs'
import ispint from 'wsemi/src/ispint.mjs'
import arrFilterByNum from 'wsemi/src/arrFilterByNum.mjs'
import arrGroupByMaxmin from 'wsemi/src/arrGroupByMaxmin.mjs'
import rang from 'wsemi/src/rang.mjs'
import isnum from 'wsemi/src/isnum.mjs'


/**
 * 針對陣列數據分組
 *
 * Unit Test: {@link https://github.com/yuda-lyu/w-statistic/blob/master/test/arrGammaInv.test.js Github}
 * @memberOf w-statistic
 * @param {Array} arr 輸入陣列,只提取有效數字(或為字串的數字)進行計算
 * @param {Integer} [n=30] 輸入分組數量整數,預設30
 * @param {Object} [opt={}] 輸入設定物件,預設{}
 * @param {Number} [opt.min=null] 輸入分組最小值數字,預設null
 * @param {Number} [opt.max=null] 輸入分組最大值數字,預設null
 * @returns {Object} 回傳數據分組資訊物件
 * @example
 *
 * let arr
 *
 * arr = ['abc', '-2.5', -2.5, '-1', -1, '-0.1', -0.1, '0', 0, '0.1', 0.1, '1', 1, '2.5', 2.5, 22.5, 'xyz']
 * console.log(bin(arr, 4))
 * // => [
 * //   {
 * //     min: -2.5,
 * //     max: 3.75,
 * //     avg: 0.625,
 * //     arr: [
 * //       -2.5, -2.5, -1, -1,
 * //       -0.1, -0.1,  0,  0,
 * //        0.1,  0.1,  1,  1,
 * //        2.5,  2.5
 * //     ]
 * //   },
 * //   { min: 3.75, max: 10, avg: 6.875, arr: [] },
 * //   { min: 10, max: 16.25, avg: 13.125, arr: [] },
 * //   { min: 16.25, max: 22.5, avg: 19.375, arr: [ 22.5 ] }
 * // ]
 *
 * arr = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6]
 * console.log(bin(arr, 3))
 * // => [
 * //   {
 * //     min: 1.1,
 * //     max: 2.9333333333333336,
 * //     avg: 2.0166666666666666,
 * //     arr: [ 1.1, 2.2 ]
 * //   },
 * //   {
 * //     min: 2.9333333333333336,
 * //     max: 4.766666666666667,
 * //     avg: 3.85,
 * //     arr: [ 3.3, 4.4 ]
 * //   },
 * //   {
 * //     min: 4.766666666666667,
 * //     max: 6.6,
 * //     avg: 5.683333333333334,
 * //     arr: [ 5.5, 6.6 ]
 * //   }
 * // ]
 *
 * arr = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6]
 * console.log(bin(arr, 5))
 * // => [
 * //   { min: 1.1, max: 2.2, avg: 1.6500000000000001, arr: [ 1.1, 2.2 ] },
 * //   { min: 2.2, max: 3.3000000000000003, avg: 2.75, arr: [ 3.3 ] },
 * //   {
 * //     min: 3.3000000000000003,
 * //     max: 4.4,
 * //     avg: 3.8500000000000005,
 * //     arr: [ 4.4 ]
 * //   },
 * //   { min: 4.4, max: 5.5, avg: 4.95, arr: [ 5.5 ] },
 * //   { min: 5.5, max: 6.6, avg: 6.05, arr: [ 6.6 ] }
 * // ]
 *
 * arr = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6]
 * console.log(bin(arr, 5, { min: 0, max: 10 }))
 * // => [
 * //   { min: 0, max: 2, avg: 1, arr: [ 1.1 ] },
 * //   { min: 2, max: 4, avg: 3, arr: [ 2.2, 3.3 ] },
 * //   { min: 4, max: 6, avg: 5, arr: [ 4.4, 5.5 ] },
 * //   { min: 6, max: 8, avg: 7, arr: [ 6.6 ] },
 * //   { min: 8, max: 10, avg: 9, arr: [] }
 * // ]
 *
 */
function bin(arr, n = 30, opt = {}) {

    //check n
    if (!ispint(n)) {
        n = 30
    }
    n = cint(n)
    // console.log('n', n)

    //arrFilterByNum
    let rs = arrFilterByNum(arr)

    //check rs
    if (size(rs) === 0) {
        return []
    }

    //rmin
    let rmin = get(opt, 'min', null)
    if (!isnum(rmin)) {
        rmin = min(rs)
    }
    rmin = cdbl(rmin)
    // console.log('rmin', rmin)

    //rmax
    let rmax = get(opt, 'max', null)
    if (!isnum(rmax)) {
        rmax = max(rs)
    }
    rmax = cdbl(rmax)
    // console.log('rmax', rmax)

    //rang
    let ts = rang(rmin, rmax, n)
    // console.log('ts', ts)

    //mm
    let mm = []
    for (let i = 0; i < size(ts) - 1; i++) {
        let minType = i === 0 ? '>=' : '>'
        let maxType = '<='
        let m = {
            min: ts[i],
            max: ts[i + 1],
            avg: (ts[i] + ts[i + 1]) / 2,
            minType,
            maxType,
        }
        mm.push(m)
    }
    // console.log('mm', mm)

    //arrGroupByMaxmin
    let gs = arrGroupByMaxmin(rs, mm)
    // console.log('gs', gs)

    //bs
    let bs = map(gs, (v) => {
        return {
            min: v.min,
            max: v.max,
            avg: v.avg,
            arr: get(v, 'items', []),
        }
    })

    return bs
}


export default bin