Last active
September 30, 2021 13:32
-
-
Save bryandh/c0cd25df7ccfdf891bf782174535f4ca to your computer and use it in GitHub Desktop.
Typescript Array utilities
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
export class ArrayUtilities { | |
/** | |
* Groups a collection by a property to a Map type. | |
* @param collection The collection to group. | |
* @param groupKeyResolver Contains the property to group by, computed from a function. | |
* @returns Map key-value pair collection with given property as key and elements with that property as values. | |
*/ | |
public static groupBy<K, T>(collection: T[], groupKeyResolver: (item: T) => K): Map<K, T[]> { | |
return collection.reduce( | |
(map: Map<K, T[]>, item: T) => { | |
// Get the group name from the groupKeyResolver function, this will be the key of the group in the array. | |
const key = groupKeyResolver(item); | |
// Add the object to the group at the computed key. | |
return map.set( | |
key, | |
map.get(key) // Retrieve any previous values at the key. | |
? map.get(key).concat(item) // Concat the object to the already existing values. | |
: [item] // Set the values as a new array with just the object. | |
); | |
}, | |
new Map<K, T[]>() // Create a new Map collection which will serve as the initial prev value. | |
); | |
} | |
/** | |
* Groups a collection by a property to a multidimensional array | |
* @param collection The collection to group | |
* @param groupKeyResolver Contains the property to group by, computed from a function. | |
* @returns T[][] Multidimensional array key-value pair collection with given property as key and elements with that property as values. | |
*/ | |
public static group<T>(collection: T[], groupKeyResolver: (item: T) => any): T[][] { | |
return collection.reduce( | |
(prev: T, next: T) => { | |
// Get the group name from the property function, this will be the index of the group in the array | |
const groupName = groupKeyResolver(next); | |
// Set the group in the array to either its previous value (prev[groupName]) | |
// if that exists, otherwise fill it with an empty array | |
prev[groupName] = prev[groupName] || []; | |
// Add the next item to the group's array | |
prev[groupName].push(next); | |
return prev; | |
}, | |
Object.create(null) | |
); | |
} | |
/** | |
* Sums a collection by a property | |
* @param collection The collection to sum | |
* @param property The property to sum, represented in a function | |
*/ | |
public static sum<T>(collection: T[], property: (item: T) => number): number { | |
return collection.reduce((prev: 0, next: T) => { | |
return prev + (isNaN(Number(property(next))) ? 0 : Number(property(next))); | |
}, 0); | |
} | |
/** | |
* Segment an array to an array of arrays based on a key within the items | |
*/ | |
public static segmentBy<T>(collection: T[], seperatorFunc: (item: T) => any): T[][] { | |
const segments = []; | |
let currentSegment: T[] = []; | |
let lastSeperator = null; | |
for (const item of collection) { | |
const currentSeperator = seperatorFunc(item); | |
// Set the initial separator | |
if (!lastSeperator) | |
lastSeperator = currentSeperator; | |
if (currentSeperator === lastSeperator) | |
// Add the item to the segment as it has the same separator as the last | |
currentSegment.push(item); | |
else { | |
// Add the current segment to the segments array as we're not adding any more items to it | |
segments.push(currentSegment); | |
// Start a new current segment with the current item | |
currentSegment = [item]; | |
lastSeperator = currentSeperator; | |
} | |
} | |
// add the last one | |
segments.push(currentSegment); | |
return segments; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment