ice.fo.utils
Version:
103 lines (87 loc) • 2.59 kB
JavaScript
import _groupBy from 'lodash/groupBy'
import _get from 'lodash/get'
import _isEqual from 'lodash/isEqual'
import _isFunction from 'lodash/isFunction'
/**
* Group a list of objects by [key] name. The [key] also supports properties path access e.g. 'user.profile.name'
*
* @example
* groupByKey([{name: 'nikochin', age: 10}, {name: 'nikochin', age: 30}, {name: 'edward', age: 10}], 'name', true); // returns [ [{name: 'nikochin', age: 10}, {name: 'nikochin', age: 30}], [{name: 'edward', age: 10}] ]
*
* @param {any[]} list
* @param {string|string[]} key
* @param {boolean} keepOrder
* @returns An list of objects list grouped by key
*/
export function groupByKey (list, key, keepOrder = false) {
if (!keepOrder) {
return Object.values(_groupBy(list, i => _get(i, key)))
}
const result = []
const firstItem = _get(list, '0')
const isFuncKey = _isFunction(key)
let previousValue = isFuncKey ? key(firstItem) : _get(firstItem, key)
let previousList = []
list.forEach((item) => {
const value = isFuncKey ? key(item) : _get(item, key)
if (_isEqual(value, previousValue)) {
previousList.push(item)
} else {
result.push(previousList)
previousList = [item]
previousValue = value
}
})
if (previousList.length) {
result.push(previousList)
}
return result
}
/**
* Merge 2 array and remove previous duplicate
*
* @param {any[]} a
* @param {any[]} b
* @param {(any) => string} indicator
* @returns
*/
export function mergeUnique (a, b, indicator = i => i.id) {
const result = []
const dict = {}
a.forEach((i, index) => {
result.push(i)
dict[indicator(i)] = index
})
b.forEach((i) => {
const foundIndex = dict[indicator(i)]
if (foundIndex != null) {
result.splice(foundIndex, 1, i)
} else {
result.push(i)
}
})
return result
}
/**
* Creates an array of elements split into groups with length size. If array can't be split evenly, the final chunk will be the remaining elements.
*
* @example
* splitIntoChunks([1,2,3,4], 2); // returns [ [1,2], [3,4] ]
* splitIntoChunks([1,2,3,4], 3); // returns [ [1,2,3], [4] ]
* splitIntoChunks([1,2,3,4], 5); // returns [ [1,2,3,4] ]
*
* @param array
* @param length
* @returns {[]}
*/
export function splitIntoChunks (array, length) {
if (array.length < length) {
return [array]
}
const result = []
const chunkCount = Math.ceil(array.length / length)
for (let i = 0; i < chunkCount; i++) {
result.push(array.slice(i * length, i * length + length))
}
return result
}