From 74b0bbd51016d12fdc88d151db83d980d9ab5c34 Mon Sep 17 00:00:00 2001 From: Kimbrian Marshall Date: Tue, 2 Jul 2024 15:31:48 +0700 Subject: [PATCH] feat(array): add mapify --- benchmarks/array/mapify.bench.ts | 28 +++++++++++++++++++++++ docs/array/mapify.mdx | 38 ++++++++++++++++++++++++++++++++ src/array/mapify.ts | 9 ++++++++ src/mod.ts | 2 ++ tests/array/mapify.test.ts | 36 ++++++++++++++++++++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 benchmarks/array/mapify.bench.ts create mode 100644 docs/array/mapify.mdx create mode 100644 src/array/mapify.ts create mode 100644 tests/array/mapify.test.ts diff --git a/benchmarks/array/mapify.bench.ts b/benchmarks/array/mapify.bench.ts new file mode 100644 index 00000000..0202b2a1 --- /dev/null +++ b/benchmarks/array/mapify.bench.ts @@ -0,0 +1,28 @@ +import * as _ from 'radashi' +import { bench } from 'vitest' + +describe('mapify', () => { + bench('with full list and identity value function', () => { + const list = [ + { id: 'a', word: 'hello' }, + { id: 'b', word: 'bye' }, + { id: 'c', word: 'oh' }, + { id: 'd', word: 'hey' }, + { id: 'e', word: 'ok' }, + ] + _.objectify( + list, + x => x.id, + x => x, + ) + }) + + bench('with empty list', () => { + _.objectify( + [], + (x: any) => x.id, + x => x, + ) + }) +}) + diff --git a/docs/array/mapify.mdx b/docs/array/mapify.mdx new file mode 100644 index 00000000..3257d085 --- /dev/null +++ b/docs/array/mapify.mdx @@ -0,0 +1,38 @@ +--- +title: mapify +group: "Array" +description: Convert an array to a map +--- + +## Basic usage + +Given an array of items, create a map with keys and values mapped by given +functions. First argument is the array to map. The second argument is the +function to determine the key for each item. The third argument is optional and +determines the value for each item. + +```ts +import * as _ from "radashi"; + +const fish = [ + { + name: "Marlin", + weight: 105, + }, + { + name: "Bass", + weight: 8, + }, + { + name: "Trout", + weight: 13, + }, +]; + +_.mapify(fish, f => f.name); // => Map(3) {'Marlin' => { name: 'Marlin', weight: 105 }, 'Bass' => { name: 'Bass', weight: 8 }, 'Trout' => { name: 'Trout', weight: 13 }} +_.mapify( + fish, + f => f.name, + f => f.weight +); // => Map(3) { 'Marlin' => 105, 'Bass' => 8, 'Trout' => 13 } +``` diff --git a/src/array/mapify.ts b/src/array/mapify.ts new file mode 100644 index 00000000..961be93d --- /dev/null +++ b/src/array/mapify.ts @@ -0,0 +1,9 @@ +export function mapify( + array: readonly T[], + getKey: (item: T) => Key, + getValue: (item: T) => Value = item => item as unknown as Value, +): Map { + const map: Map = new Map(); + array.forEach(item => map.set(getKey(item), getValue(item))) + return map; +} diff --git a/src/mod.ts b/src/mod.ts index bbef98d5..590d2fa2 100644 --- a/src/mod.ts +++ b/src/mod.ts @@ -11,6 +11,7 @@ export * from './array/intersects.ts' export * from './array/iterate.ts' export * from './array/last.ts' export * from './array/list.ts' +export * from './array/mapify.ts' export * from './array/max.ts' export * from './array/merge.ts' export * from './array/min.ts' @@ -105,3 +106,4 @@ export * from './typed/isPrimitive.ts' export * from './typed/isPromise.ts' export * from './typed/isString.ts' export * from './typed/isSymbol.ts' + diff --git a/tests/array/mapify.test.ts b/tests/array/mapify.test.ts new file mode 100644 index 00000000..d4c106ac --- /dev/null +++ b/tests/array/mapify.test.ts @@ -0,0 +1,36 @@ +import * as _ from 'radashi' + +describe('mapify', () => { + const list = [ + { id: 'a', word: 'hello' }, + { id: 'b', word: 'bye' }, + { id: 'c', word: 'oh' }, + { id: 'd', word: 'hey' }, + { id: 'e', word: 'ok' }, + ] + test('returns correct map of values', () => { + const result = _.mapify( + list, + x => x.id, + x => x, + ) + expect(result).toBeTypeOf(typeof new Map()) + expect(result.size).toBe(5) + expect(result.get("a")?.word).toBe('hello') + expect(result.get("b")?.word).toBe('bye') + }) + test('does not fail on empty input list', () => { + const result = _.mapify( + [], + (x: any) => x.id, + x => x, + ) + expect(result).toBeTypeOf(typeof new Map()) + }) + test('defaults value to array item', () => { + const result = _.mapify(list.slice(0, 1), x => x.id) + expect(result).toBeTypeOf(typeof new Map()) + expect(result.size).toBe(1) + expect(result.get("a")?.word).toBe('hello') + }) +})