2021-10-09 12:50:47 +03:00
|
|
|
type Categories<T> = {
|
|
|
|
[key: string]: (item: T) => boolean;
|
|
|
|
};
|
|
|
|
|
|
|
|
type CategoryReturnType<T, C extends Categories<T>> = {
|
|
|
|
[key in keyof C]: T[];
|
|
|
|
};
|
|
|
|
|
2023-05-08 22:58:51 +03:00
|
|
|
function initCategories<T, C extends Categories<T>>(categories: C): CategoryReturnType<T, C> {
|
2021-10-09 12:50:47 +03:00
|
|
|
return Object.keys(categories).reduce((map, key) => {
|
|
|
|
map[key] = [];
|
|
|
|
return map;
|
|
|
|
}, {}) as CategoryReturnType<T, C>;
|
|
|
|
}
|
|
|
|
|
2023-05-08 22:58:51 +03:00
|
|
|
export function categorize<T, C extends Categories<T>>(arr: T[], categories: C): CategoryReturnType<T, C> {
|
2021-10-09 12:50:47 +03:00
|
|
|
const result = initCategories<T, C>(categories);
|
|
|
|
const categoryEntries = Object.entries(categories);
|
|
|
|
|
|
|
|
itemLoop: for (const item of arr) {
|
|
|
|
for (const [category, fn] of categoryEntries) {
|
|
|
|
if (fn(item)) {
|
|
|
|
result[category].push(item);
|
|
|
|
continue itemLoop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|