import {isArray, isObject, isString} from "./typer.js";
import {cloneDeep, deepAssign} from "./clone.js";
import {jsonParse, jsonStringify, safeJsonParse} from "./str.js";
import {noop} from "./other.js";
/**
* @param value
* @returns {any}
*/
export const cloneByJSON = (value)=>{
return jsonParse(jsonStringify(value));
}
/**
* @description set value to obj with specified key path
* @param {object} obj
* @param {string} key
* @param {*} value
* @returns {*}
*/
export function setter(obj, key='', value) {
if(!isObject(obj)){
return;
}
let originObj = obj;
let keyPath = key.split('.'); //a.b.c = 2
let abovePart = keyPath.slice(0, keyPath.length - 1);
let lastPart = keyPath[keyPath.length - 1];
for (let keyPart of abovePart) {
let objValue = obj[keyPart];
if (!isObject(objValue)) {
obj[keyPart] = {};
}
obj = obj[keyPart];
}
obj[lastPart] = value;
return originObj;
}
export function eachObject(obj={}, callback=noop, prePath = '') {
callback(prePath, obj);
if (isObject(obj)) {
if (isArray(obj)) {
obj.forEach((item, index) => {
eachObject(item, callback, `${prePath}[${index}]`);
});
} else {
Object.keys(obj).forEach(key => {
let value = obj[key];
eachObject(
value,
callback,
`${prePath ? prePath + '.' : prePath}${key}`,
);
});
}
}
}
/**
* @description get combination of object by objDef. But it doesn't support definition about array
* @param {object} obj original obj data
* @param {object} objDef the definition object of getting fields of obj
* @example
* import { getCombinationOfObject } from * "@ustinian-wang/kit";
* let testData ={ a: 1, b: 2 };
* let dataList = getCombinationOfObject(testData, {
* a: [1, 2,3],
* b: [4, 5, 6]
* });
* let newData = deepAssign( {}, testData, dataList[0] );
* @returns {Array<object>}
*/
export function getCombinationOfObject(obj, objDef) {
let pathObj = {};
/**
* {
* a: [],
* b: [],
* c: [],
* d: []
* }
*/
eachObject(objDef, (path, value) => {
if (isArray(value)) {
//拿到数组,说明拿到范围值
pathObj[path] = value;
}
});
let paths = Object.keys(pathObj);
let arrays = paths.map(path => pathObj[path]);
let combinations = getCombination(arrays);
return combinations.map(result => {
let tmpObj = {};
paths.forEach((path, index) => {
let value = result[index];
setter(tmpObj, path, value);
});
return deepAssign(cloneDeep(obj), tmpObj);
});
}
/**
* @description 生成多个数组的组合列表。
* @param {Array<Array<*>>} arrays - 一个数组的数组,每个数组代表一组可选元素。
* @returns {Array<Array<*>>} - 返回一个包含所有可能组合的数组。
* @example
* // 示例用法
* let combos = getCombination([
* [1, 2],
* [3, 4],
* [5, 6]
* ]);
*
* console.log(combos); // [[1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
*/
function getCombination(arrays) {
let result = [];
function helper(combination, index) {
if (index === arrays.length) {
result.push(combination);
} else {
for (const element of arrays[index]) {
helper([...combination, element], index + 1);
}
}
}
helper([], 0);
return result;
}
/**
* @description translate value to object if value is type of object
* @param {object|string} value
* @returns {*}
*/
export function toObject(value) {
if (isObject(value)) {
return value;
}
return safeJsonParse(value || '{}');
}
/**
* @description read data's key
* @param {object} obj
* @param {string} path //eg: a.b.c
* @param {any} [defaultValue=undefined]
* @returns {any}
*/
export function getter(obj, path='', defaultValue = undefined) {
if (!isObject(obj) || !isString(path)) {
return defaultValue;
}
const props = path.split(".");
let result = obj;
for (const prop of props) {
const isArrayIndex = /\[\d+]/.test(prop);
if (isArrayIndex) {
const index = parseInt(prop.match(/\d+/)[0]);
result = result[index];
} else {
result = result[prop];
}
if (result === undefined) {
return defaultValue;
}
}
return result;
}
Source