import get from 'lodash-es/get.js'
import map from 'lodash-es/map.js'
import join from 'lodash-es/join.js'
import size from 'lodash-es/size.js'
import keys from 'lodash-es/keys.js'
import isNumber from 'lodash-es/isNumber.js'
import isSymbol from 'lodash-es/isSymbol.js'
import cloneDeep from 'lodash-es/cloneDeep.js'
import isestr from './isestr.mjs'
import iseobj from './iseobj.mjs'
import isearr from './isearr.mjs'
import isnum from './isnum.mjs'
import isobj from './isobj.mjs'
import isarr from './isarr.mjs'
import cstr from './cstr.mjs'
import treeObj from './treeObj.mjs'
/**
* 展平物件或陣列成為關聯陣列
*
* Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/flattenToConn.test.mjs Github}
* @memberOf wsemi
* @param {Array|Object} data 輸入項目物件或陣列
* @param {Object} [opt={}] 輸入設定物件,預設{}
* @param {String} [bindKey='id'] 輸入識別用欄位字串,預設'id'
* @param {String} [bindParent='parentId'] 輸入存放父節點識別用欄位字串,預設'parentId'
* @param {String} [bindBelong='key'] 輸入當父節點為物件或陣列時,存放自身所屬鍵值字串,預設'key'
* @param {String} [bindText='text'] 輸入存放值欄位字串,預設'text'
* @param {String} [bindType='type'] 輸入存放值種類欄位字串,預設'type'
* @param {String} [bindNumOfChilren='numOfChilren'] 輸入存放值為物件或陣列時所屬子節點數量欄位字串,預設'numOfChilren'
* @returns {Array} 回傳關聯陣列
* @example
*
* let r
*
* let obj = {
* a: 1,
* b: 12.3,
* c: 'abc',
* d: '45-de',
* x: true,
* y: null,
* z: function() {},
* e: [],
* f: [
* 91,
* 912.3,
* 'abc',
* '945-de',
* true,
* null,
* function() {},
* [
* 5,
* 54.3,
* 'xyz',
* ]
* ],
* g: {},
* h: {
* ga: 81,
* gb: 812.3,
* gc: 'abc',
* gd: '845-de',
* ge: [
* 71,
* 712.3,
* 'abc',
* '745-de',
* true,
* null,
* function() {},
* ],
* gf: {
* gfa: 61,
* gfb: 612.3,
* gfc: 'abc',
* gfd: '645-de',
* gfe: true,
* gff: null,
* gfg: function() {},
* },
* gx: true,
* gy: null,
* gz: function() {},
* },
* i: Symbol('foo'),
* [Symbol('i-sym-key-a')]: 'i-sym-value',
* [Symbol('i-sym-key-b')]: {
* symfa: 61,
* symfb: 612.3,
* symfc: 'abc',
* symfd: '645-de',
* symfe: true,
* symff: null,
* symfg: function() {},
* },
* }
* r = flattenToConn(obj)
* console.log('flattenToConn obj', r)
* // => flattenToConn obj [
* // { id: 'a', parentId: '', type: 'node', key: 'a', text: 1 },
* // { id: 'b', parentId: '', type: 'node', key: 'b', text: 12.3 },
* // { id: 'c', parentId: '', type: 'node', key: 'c', text: 'abc' },
* // { id: 'd', parentId: '', type: 'node', key: 'd', text: '45-de' },
* // { id: 'x', parentId: '', type: 'node', key: 'x', text: true },
* // { id: 'y', parentId: '', type: 'node', key: 'y', text: null },
* // {
* // id: 'z',
* // parentId: '',
* // type: 'node',
* // key: 'z',
* // text: [Function: z]
* // },
* // { id: 'e', parentId: '', type: 'array', key: 'e', numOfChilren: 0 },
* // { id: 'f', parentId: '', type: 'array', key: 'f', numOfChilren: 8 },
* // { id: 'f-0', parentId: 'f', type: 'node', key: 0, text: 91 },
* // { id: 'f-1', parentId: 'f', type: 'node', key: 1, text: 912.3 },
* // { id: 'f-2', parentId: 'f', type: 'node', key: 2, text: 'abc' },
* // { id: 'f-3', parentId: 'f', type: 'node', key: 3, text: '945-de' },
* // { id: 'f-4', parentId: 'f', type: 'node', key: 4, text: true },
* // { id: 'f-5', parentId: 'f', type: 'node', key: 5, text: null },
* // {
* // id: 'f-6',
* // parentId: 'f',
* // type: 'node',
* // key: 6,
* // text: [Function (anonymous)]
* // },
* // { id: 'f-7', parentId: 'f', type: 'array', key: 7, numOfChilren: 3 },
* // { id: 'f-7-0', parentId: 'f-7', type: 'node', key: 0, text: 5 },
* // { id: 'f-7-1', parentId: 'f-7', type: 'node', key: 1, text: 54.3 },
* // { id: 'f-7-2', parentId: 'f-7', type: 'node', key: 2, text: 'xyz' },
* // { id: 'g', parentId: '', type: 'object', key: 'g', numOfChilren: 0 },
* // { id: 'h', parentId: '', type: 'object', key: 'h', numOfChilren: 9 },
* // { id: 'h-ga', parentId: 'h', type: 'node', key: 'ga', text: 81 },
* // { id: 'h-gb', parentId: 'h', type: 'node', key: 'gb', text: 812.3 },
* // { id: 'h-gc', parentId: 'h', type: 'node', key: 'gc', text: 'abc' },
* // {
* // id: 'h-gd',
* // parentId: 'h',
* // type: 'node',
* // key: 'gd',
* // text: '845-de'
* // },
* // {
* // id: 'h-ge',
* // parentId: 'h',
* // type: 'array',
* // key: 'ge',
* // numOfChilren: 7
* // },
* // { id: 'h-ge-0', parentId: 'h-ge', type: 'node', key: 0, text: 71 },
* // { id: 'h-ge-1', parentId: 'h-ge', type: 'node', key: 1, text: 712.3 },
* // { id: 'h-ge-2', parentId: 'h-ge', type: 'node', key: 2, text: 'abc' },
* // {
* // id: 'h-ge-3',
* // parentId: 'h-ge',
* // type: 'node',
* // key: 3,
* // text: '745-de'
* // },
* // { id: 'h-ge-4', parentId: 'h-ge', type: 'node', key: 4, text: true },
* // { id: 'h-ge-5', parentId: 'h-ge', type: 'node', key: 5, text: null },
* // {
* // id: 'h-ge-6',
* // parentId: 'h-ge',
* // type: 'node',
* // key: 6,
* // text: [Function (anonymous)]
* // },
* // {
* // id: 'h-gf',
* // parentId: 'h',
* // type: 'object',
* // key: 'gf',
* // numOfChilren: 7
* // },
* // {
* // id: 'h-gf-gfa',
* // parentId: 'h-gf',
* // type: 'node',
* // key: 'gfa',
* // text: 61
* // },
* // {
* // id: 'h-gf-gfb',
* // parentId: 'h-gf',
* // type: 'node',
* // key: 'gfb',
* // text: 612.3
* // },
* // {
* // id: 'h-gf-gfc',
* // parentId: 'h-gf',
* // type: 'node',
* // key: 'gfc',
* // text: 'abc'
* // },
* // {
* // id: 'h-gf-gfd',
* // parentId: 'h-gf',
* // type: 'node',
* // key: 'gfd',
* // text: '645-de'
* // },
* // {
* // id: 'h-gf-gfe',
* // parentId: 'h-gf',
* // type: 'node',
* // key: 'gfe',
* // text: true
* // },
* // {
* // id: 'h-gf-gff',
* // parentId: 'h-gf',
* // type: 'node',
* // key: 'gff',
* // text: null
* // },
* // {
* // id: 'h-gf-gfg',
* // parentId: 'h-gf',
* // type: 'node',
* // key: 'gfg',
* // text: [Function: gfg]
* // },
* // { id: 'h-gx', parentId: 'h', type: 'node', key: 'gx', text: true },
* // { id: 'h-gy', parentId: 'h', type: 'node', key: 'gy', text: null },
* // {
* // id: 'h-gz',
* // parentId: 'h',
* // type: 'node',
* // key: 'gz',
* // text: [Function: gz]
* // },
* // { id: 'i', parentId: '', type: 'node', key: 'i', text: Symbol(foo) },
* // {
* // id: 'Symbol(i-sym-key-a)',
* // parentId: '',
* // type: 'node',
* // text: 'i-sym-value'
* // },
* // {
* // id: 'Symbol(i-sym-key-b)',
* // parentId: '',
* // type: 'object',
* // numOfChilren: 7
* // },
* // {
* // id: 'Symbol(i-sym-key-b)-symfa',
* // parentId: 'Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symfa',
* // text: 61
* // },
* // {
* // id: 'Symbol(i-sym-key-b)-symfb',
* // parentId: 'Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symfb',
* // text: 612.3
* // },
* // {
* // id: 'Symbol(i-sym-key-b)-symfc',
* // parentId: 'Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symfc',
* // text: 'abc'
* // },
* // {
* // id: 'Symbol(i-sym-key-b)-symfd',
* // parentId: 'Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symfd',
* // text: '645-de'
* // },
* // {
* // id: 'Symbol(i-sym-key-b)-symfe',
* // parentId: 'Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symfe',
* // text: true
* // },
* // {
* // id: 'Symbol(i-sym-key-b)-symff',
* // parentId: 'Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symff',
* // text: null
* // },
* // {
* // id: 'Symbol(i-sym-key-b)-symfg',
* // parentId: 'Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symfg',
* // text: [Function: symfg]
* // }
* // ]
*
* let arr = [
* 91,
* 912.3,
* 'abc',
* '945-de',
* true,
* null,
* function() {},
* [
* 5,
* 54.3,
* 'xyz',
* {
* gf: {
* gfa: 61,
* gfb: 612.3,
* gfc: 'abc',
* gfd: '645-de',
* gfe: true,
* gff: null,
* gfg: function() {},
* },
* },
* ],
* {
* h: {
* ga: 81,
* gb: 812.3,
* gc: 'abc',
* gd: '845-de',
* ge: [
* 71,
* 712.3,
* 'abc',
* '745-de',
* true,
* null,
* function() {},
* ],
* gx: true,
* gy: null,
* gz: function() {},
* },
* i: Symbol('foo'),
* [Symbol('i-sym-key-a')]: 'i-sym-value',
* [Symbol('i-sym-key-b')]: {
* symfa: 61,
* symfb: 612.3,
* symfc: 'abc',
* symfd: '645-de',
* symfe: true,
* symff: null,
* symfg: function() {},
* },
* },
* ]
* r = flattenToConn(arr)
* console.log('flattenToConn arr', r)
* // => flattenToConn arr [
* // { id: '0', parentId: '', type: 'node', key: 0, text: 91 },
* // { id: '1', parentId: '', type: 'node', key: 1, text: 912.3 },
* // { id: '2', parentId: '', type: 'node', key: 2, text: 'abc' },
* // { id: '3', parentId: '', type: 'node', key: 3, text: '945-de' },
* // { id: '4', parentId: '', type: 'node', key: 4, text: true },
* // { id: '5', parentId: '', type: 'node', key: 5, text: null },
* // {
* // id: '6',
* // parentId: '',
* // type: 'node',
* // key: 6,
* // text: [Function (anonymous)]
* // },
* // { id: '7', parentId: '', type: 'array', key: 7, numOfChilren: 4 },
* // { id: '7-0', parentId: '7', type: 'node', key: 0, text: 5 },
* // { id: '7-1', parentId: '7', type: 'node', key: 1, text: 54.3 },
* // { id: '7-2', parentId: '7', type: 'node', key: 2, text: 'xyz' },
* // { id: '7-3', parentId: '7', type: 'object', key: 3, numOfChilren: 1 },
* // {
* // id: '7-3-gf',
* // parentId: '7-3',
* // type: 'object',
* // key: 'gf',
* // numOfChilren: 7
* // },
* // {
* // id: '7-3-gf-gfa',
* // parentId: '7-3-gf',
* // type: 'node',
* // key: 'gfa',
* // text: 61
* // },
* // {
* // id: '7-3-gf-gfb',
* // parentId: '7-3-gf',
* // type: 'node',
* // key: 'gfb',
* // text: 612.3
* // },
* // {
* // id: '7-3-gf-gfc',
* // parentId: '7-3-gf',
* // type: 'node',
* // key: 'gfc',
* // text: 'abc'
* // },
* // {
* // id: '7-3-gf-gfd',
* // parentId: '7-3-gf',
* // type: 'node',
* // key: 'gfd',
* // text: '645-de'
* // },
* // {
* // id: '7-3-gf-gfe',
* // parentId: '7-3-gf',
* // type: 'node',
* // key: 'gfe',
* // text: true
* // },
* // {
* // id: '7-3-gf-gff',
* // parentId: '7-3-gf',
* // type: 'node',
* // key: 'gff',
* // text: null
* // },
* // {
* // id: '7-3-gf-gfg',
* // parentId: '7-3-gf',
* // type: 'node',
* // key: 'gfg',
* // text: [Function: gfg]
* // },
* // { id: '8', parentId: '', type: 'object', key: 8, numOfChilren: 2 },
* // {
* // id: '8-h',
* // parentId: '8',
* // type: 'object',
* // key: 'h',
* // numOfChilren: 8
* // },
* // { id: '8-h-ga', parentId: '8-h', type: 'node', key: 'ga', text: 81 },
* // {
* // id: '8-h-gb',
* // parentId: '8-h',
* // type: 'node',
* // key: 'gb',
* // text: 812.3
* // },
* // {
* // id: '8-h-gc',
* // parentId: '8-h',
* // type: 'node',
* // key: 'gc',
* // text: 'abc'
* // },
* // {
* // id: '8-h-gd',
* // parentId: '8-h',
* // type: 'node',
* // key: 'gd',
* // text: '845-de'
* // },
* // {
* // id: '8-h-ge',
* // parentId: '8-h',
* // type: 'array',
* // key: 'ge',
* // numOfChilren: 7
* // },
* // {
* // id: '8-h-ge-0',
* // parentId: '8-h-ge',
* // type: 'node',
* // key: 0,
* // text: 71
* // },
* // {
* // id: '8-h-ge-1',
* // parentId: '8-h-ge',
* // type: 'node',
* // key: 1,
* // text: 712.3
* // },
* // {
* // id: '8-h-ge-2',
* // parentId: '8-h-ge',
* // type: 'node',
* // key: 2,
* // text: 'abc'
* // },
* // {
* // id: '8-h-ge-3',
* // parentId: '8-h-ge',
* // type: 'node',
* // key: 3,
* // text: '745-de'
* // },
* // {
* // id: '8-h-ge-4',
* // parentId: '8-h-ge',
* // type: 'node',
* // key: 4,
* // text: true
* // },
* // {
* // id: '8-h-ge-5',
* // parentId: '8-h-ge',
* // type: 'node',
* // key: 5,
* // text: null
* // },
* // {
* // id: '8-h-ge-6',
* // parentId: '8-h-ge',
* // type: 'node',
* // key: 6,
* // text: [Function (anonymous)]
* // },
* // {
* // id: '8-h-gx',
* // parentId: '8-h',
* // type: 'node',
* // key: 'gx',
* // text: true
* // },
* // {
* // id: '8-h-gy',
* // parentId: '8-h',
* // type: 'node',
* // key: 'gy',
* // text: null
* // },
* // {
* // id: '8-h-gz',
* // parentId: '8-h',
* // type: 'node',
* // key: 'gz',
* // text: [Function: gz]
* // },
* // {
* // id: '8-i',
* // parentId: '8',
* // type: 'node',
* // key: 'i',
* // text: Symbol(foo)
* // },
* // {
* // id: '8-Symbol(i-sym-key-a)',
* // parentId: '8',
* // type: 'node',
* // text: 'i-sym-value'
* // },
* // {
* // id: '8-Symbol(i-sym-key-b)',
* // parentId: '8',
* // type: 'object',
* // numOfChilren: 7
* // },
* // {
* // id: '8-Symbol(i-sym-key-b)-symfa',
* // parentId: '8-Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symfa',
* // text: 61
* // },
* // {
* // id: '8-Symbol(i-sym-key-b)-symfb',
* // parentId: '8-Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symfb',
* // text: 612.3
* // },
* // {
* // id: '8-Symbol(i-sym-key-b)-symfc',
* // parentId: '8-Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symfc',
* // text: 'abc'
* // },
* // {
* // id: '8-Symbol(i-sym-key-b)-symfd',
* // parentId: '8-Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symfd',
* // text: '645-de'
* // },
* // {
* // id: '8-Symbol(i-sym-key-b)-symfe',
* // parentId: '8-Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symfe',
* // text: true
* // },
* // {
* // id: '8-Symbol(i-sym-key-b)-symff',
* // parentId: '8-Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symff',
* // text: null
* // },
* // {
* // id: '8-Symbol(i-sym-key-b)-symfg',
* // parentId: '8-Symbol(i-sym-key-b)',
* // type: 'node',
* // key: 'symfg',
* // text: [Function: symfg]
* // }
* // ]
*
*/
function flattenToConn(data, opt = {}) {
//check
if (!iseobj(data) && !isearr(data)) {
return []
}
//bindKey
let bindKey = get(opt, 'bindKey', null)
if (!isestr(bindKey)) {
bindKey = 'id'
}
//bindParent
let bindParent = get(opt, 'bindParent', null)
if (!isestr(bindParent)) {
bindParent = 'parentId'
}
//bindBelong
let bindBelong = get(opt, 'bindBelong', null)
if (!isestr(bindBelong)) {
bindBelong = 'key'
}
//bindText
let bindText = get(opt, 'bindText', null)
if (!isestr(bindText)) {
bindText = 'text'
}
//bindType
let bindType = get(opt, 'bindType', null)
if (!isestr(bindType)) {
bindType = 'type'
}
//bindNumOfChilren
let bindNumOfChilren = get(opt, 'bindNumOfChilren', null)
if (!isestr(bindNumOfChilren)) {
bindNumOfChilren = 'numOfChilren'
}
function genId(nk, k) {
nk = cloneDeep(nk)
nk = map(nk, (v) => {
if (isSymbol(v)) {
return cstr(v)
}
return v
})
if (isSymbol(k)) {
k = cstr(k)
}
// if (isSymbol(i)) {
// i = cstr(i)
// }
if (isestr(k) || isnum(k)) {
nk.push(k)
}
let c = join(nk, '-')
// if (isestr(i) || isnum(i)) {
// c = `${i}-${c}`
// }
return c
}
//nodes
let nodes = []
treeObj(data, (value, key, nk) => {
// console.log('nk:', nk, 'key:', key, 'value:', value)
//idSelf
let idSelf = genId(nk, key)
//idParent
let idParent = genId(nk, null)
//type
let type = 'node'
if (isobj(value)) {
type = 'object'
}
else if (isarr(value)) {
type = 'array'
}
//node
let node = {
[bindKey]: idSelf,
[bindParent]: idParent,
[bindType]: type,
}
//bindBelong
if (isestr(key) || isNumber(key)) {
node[bindBelong] = key
}
//bindText
if (!isobj(value) && !isarr(value)) {
node[bindText] = value
}
//bindNumOfChilren
if (isobj(value) || isarr(value)) {
let numOfChilren = null
if (isobj(value)) {
numOfChilren = size(keys(value))
}
else if (isarr(value)) {
numOfChilren = size(value)
}
node[bindNumOfChilren] = numOfChilren
}
//push
nodes.push(node)
return value
}, { force: true })
// console.log('nodes', nodes)
return nodes
}
export default flattenToConn