Last active
March 4, 2019 03:53
-
-
Save ccurtin/2ab4f30e4062928d6797ce98da945e3c to your computer and use it in GitHub Desktop.
Creates index keys based on key matches for an array of objects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Creates index keys. Groups an array of objects by the specified key group. | |
* Note: if there are multiple objects with the same key and the type arg is set to `object`, only the frst match will be included in the result | |
* @exmaple: | |
* const users = [{name:"jill", favColor:"teal"}, {name:"kim", favColor:"blue"},{name:"rachel", favColor:"teal"}] | |
* groupArrayItemsByKey(users, 'favColor') | |
* output: | |
* { | |
* teal":[ | |
* {"name":"jill","favColor":"teal"}, | |
* {"name":"rachel","favColor":"teal"} | |
* ], | |
* "blue":{"name":"kim","favColor":"blue"} // NOTICE: if `type` was set to `array`, the `blue` key would be a 0-indexed array instead of an object | |
* } | |
* @param {array} items An array of objects | |
* @param {string} key The key to group by | |
* @param {string} type Enables user to force key match content as an array|object. type="object" will always ONLY include a single match in the result(ignoring any additional key matches in the items array). | |
* @return {object} The items grouped by the key | |
*/ | |
const groupArrayItemsByKey = (items, key, type) => { | |
const itemKeys = items.map(x => x[key]) | |
return items.reduce((acc, current) => { | |
hasMultiple = type !== 'object' ? itemKeys.indexOf(current[key]) < itemKeys.lastIndexOf(current[key]) : false | |
asArray = hasMultiple ? ( acc[current[key]] || [] ).concat(current) : (type == 'array' ? [current] : (current || {})) | |
asObject = current || {} | |
// will store as Array(if multiple `current[key]` keys are found in `items`) or stores it as Object if only one instance of `current[key]` is found in `items` | |
mixed = hasMultiple ? asArray : asObject, | |
data = !type ? mixed : (type === 'object' ? asObject : asArray) | |
return Object.assign(acc, { [current[key]]: data })}, {}) | |
} | |
// Minified Version: | |
// groupArrayItemsByKey=((a,e,t)=>{r=a.map(a=>a[e]);return a.reduce((a,s)=>(h="object"!==t&&r.indexOf(s[e])<r.lastIndexOf(s[e]),l=h?(a[s[e]]||[]).concat(s):"array"==t?[s]:s||{},o=s||{},mixed=h?l:o,data=t?"object"===t?o:l:mixed,Object.assign(a,{[s[e]]:data})),{})}); | |
/** | |
* Takes a shallow array of objects and will return an Object with unique "keys" based on the key | |
* @param {array} items | |
* @param {string} keys The key to sort by | |
* @return {object} New object with unique key values based on the "key" argument. Each key in the object is an array of the grouped objects by that key | |
* @example | |
* const items = [{type:"food", name:"hotdog"}, {type:"drink", name:"pepsi-cola"}, {type:"food", name:"pizza"}] | |
* const result = groupArrayByKey (items, 'type') | |
* @result: | |
* { | |
* food: [{type:"food", name:"hotdog"}, {type:"food", name:"pizza"}], | |
* drink: [{type:"drink", name:"pepsi-cola"}] | |
* } | |
* | |
*/ | |
export const groupArrayByKey = (items, key) => { | |
return items.reduce((acc, current) => Object.assign(acc, { [current[key]]:( acc[current[key]] || [] ).concat(current) }), {}) | |
} | |
// slightly more performant version that always returns array values | |
export const groupBy = (arr, key) => { | |
return arr.reduce(function(acc, x) { | |
(acc[x[key]] = acc[x[key]] || []).push(x) | |
return acc | |
}, {}) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment