import {equals, isArray, isFunction, isNumber, isObject, isString} from "./typer";
import {cloneDeep,} from "./clone";
import {noop} from "./other.js";
/**
* @description group map by field or handler to map object
* @param {array<*>} list
* @param {string | function} fieldOrHandler
* @returns {object}
*/
export function array2Map(list = [], fieldOrHandler = '') {
let obj = {};
if (!isArray(list)) {
list = [];
}
list.forEach(function(item) {
let value;
if (isFunction(fieldOrHandler)) {
value = fieldOrHandler(item);
} else {
value = item[fieldOrHandler];
}
if (!obj[value]) {
obj[value] = [];
}
obj[value].push(item);
});
return obj;
}
/**
* @description collecting some field of item to generate list;
* @param {array} itemList target list
* @param {string} field
* @returns {Array}
*/
export function getFieldList(itemList = [], field = '') {
if (!isArray(itemList)) {
itemList = [];
}
return itemList.map(function(item) {
if (isObject(item) || isArray(item)) {
return item[field];
} else {
return undefined;
}
});
}
/**
* @typedef {object} SplitListByConditionResult
* @property {array} trueList
* @property {array} falseList
*/
/**
* separating list to true list and false list
* @param {array} list
* @param {function} [predicate=noop]
* @returns {SplitListByConditionResult}
*/
export function splitArrayByPredicate(list, predicate = noop) {
let trueList = [];
let falseList = [];
if (!isArray(list)) {
list = [];
}
list.forEach(function(item) {
if (isFunction(predicate) && predicate(item)) {
trueList.push(item);
} else {
falseList.push(item);
}
});
return {
trueList,
falseList,
};
}
/**
* @description get first item when field is equals with others in memory reference
* @param {Array<object>} list
* @param {string} field
* @param {any} value
* @returns {object|null}
*/
export function getFirstByField(list, field, value) {
if (!isArray(list)) {
list = [];
}
if (!isString(field)) {
field = '';
}
return list.find(function(item) {
return item[field] === value;
});
}
/**
* @description insert elements to circle array
* @param {Object} options
* @param {Array<any>} options.circleArray the last is previous of the first in logic
* @param {Array<any>} options.array
* @param {number} [options.circleArrayIndex=0]
* @param {Function} options.match
* @returns {Array<any>}
*/
export function insertArrayToCircleArray(options = {}) {
if(!isObject(options)) {
options = {};
}
let {
circleArray = [],
array = [],
circleArrayIndex = 0,
match = equals,
} = options;
circleArray = cloneDeep(circleArray);
array = cloneDeep(array);
array = array.slice(0, circleArray.length);
let isZero = circleArrayIndex === 0;
if (isZero) {
circleArrayIndex = circleArrayIndex + 1;
}
circleArrayIndex = circleArrayIndex % circleArray.length;
if (isZero) {
circleArrayIndex = circleArrayIndex - 1;
}
array.forEach(function(item) {
circleArrayIndex = fixArrayIndex(circleArray, circleArrayIndex);
let originItem = circleArray[circleArrayIndex];
if (!match(item, originItem)) {
circleArray[circleArrayIndex] = item;
}
circleArrayIndex++;
});
return circleArray;
}
/**
* @description get elements of circleArray
* @param {array} circleArray
* @param {number} index
* @param {number} length
* @returns {Array<any>}
*/
export function getElementsOfCircleArray(
circleArray = [],
index = 0,
length = 0,
) {
length = length > circleArray.length ? circleArray.length : length;
index = fixArrayIndex(circleArray, index);
let newArray = [];
for (let i = 0; i < length; i++) {
newArray.push(circleArray[index]);
index = index + 1;
if (index > circleArray.length - 1) {
index = 0;
}
}
return newArray;
}
/**
* @description fix index of array
* @param {array} array
* @param {number} index
* @returns {*}
*/
export function fixArrayIndex(array, index) {
if (!isArray(array)) {
array = [];
}
if (!isNumber(index)) {
index = 0;
}
if (array.length === 0) {
return 0;
}
index = index % array.length;
if (index < 0) {
index = index + array.length;
}
if (index > array.length - 1) {
index = index - array.length;
}
return index;
}
/**
* @description is number array
* @param {Array<any>} array
* @returns {*}
*/
export function isNumberArray(array) {
return isTypeArray(array, isNumber);
}
export function isArrayWithElements(array){
return isArray(array) && array.length>0;
}
/**
* @description is array with elements that match typeExpect
* @param {array} value
* @param {function} typeExpect
* @returns {*}
*/
export function isTypeArray(value, typeExpect=noop) {
return isArrayWithElements(value) && value.every( typeExpect);
}
/**
* @description remove specified element from array
* @param {array<object>} array
* @param {string} field
* @param {*} value
* @return {array<object>}
*/
export function removeElementsOfArray(array, field, value) {
if(!isArrayWithElements(array) || !isString(field)) {
return array;
}
let index = array.findIndex(function(item) {
return item[field] === value;
});
if (index !== -1) {
array.splice(index, 1);
}
return array;
}
/**
* @description translate object to map struct eg: [{a:1},{a:2}] => {1:{a:1}, 2:{a:2}}
* @param {Array} list
* @param {string|function} uniqueFieldOrHandler
* @returns {{}}
*/
export function uniqueArray2Map(list = [], uniqueFieldOrHandler = '') {
let arrayMap = array2Map(list, uniqueFieldOrHandler);
let finalMap = {};
Object.keys(arrayMap).forEach(function(key) {
finalMap[key] = arrayMap[key][0];
});
return finalMap;
}
/**
* @description get first item when field is equals with others
* @param {Array<object>} list
* @param {string} [field='']
* @param {*} value
* @returns {object|undefined}
*/
export function getFirstByFieldEquals(list=[], field='', value) {
return list.find(function(item) {
return equals(item[field], value);
});
}
/**
* @description sort array by field
* @param {Array<object>} data
* @param {string} field
* @param {string} order desc, asc. default is desc
* @return {*}
*/
export function sortObjectArray(data, field, order='desc') {
if(!isTypeArray(data, isObject) || !isString(field)) {
return;
}
// 比较函数根据指定字段和排序方式定义排序规则
function compare(a, b) {
if (order === 'asc') {
if (a[field] < b[field]) {
return -1;
} else if (a[field] > b[field]) {
return 1;
}
} else if (order === 'desc') {
if (a[field] > b[field]) {
return -1;
} else if (a[field] < b[field]) {
return 1;
}
}
return 0;
}
// 使用比较函数进行排序
data.sort(compare);
return data;
}
/**
* @description check if value is array with string type
* @param {*} value
* @returns {boolean}
*/
export function isStringArray(value) {
return isTypeArray(value, isString);
}
/**
* @description get difference between two arrays
* @param {Array<any>} one
* @param {Array<any>} two
* @returns {Array<any>}
*/
export function diffArrays(one, two) {
let over = [];
for (let part of one) {
if (!two.includes(part)) {
over.push(part);
}
}
return over;
}
Source