Skip to content

Commit

Permalink
feat: ubimap filter()
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurfiorette committed Dec 4, 2024
1 parent b15c608 commit 6e6f800
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 9 deletions.
2 changes: 1 addition & 1 deletion packages/ubimap/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ubimap",
"version": "1.0.2",
"version": "1.0.3",
"description": "A safe, typed, enumerable bidirectional map that ensures unique values and supports compound keys.",
"homepage": "https://tinylibs.js.org/packages/ubimap",
"bugs": "https://github.com/arthurfiorette/tinylibs/issues",
Expand Down
67 changes: 59 additions & 8 deletions packages/ubimap/src/ubimap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,19 @@ export class UbiMap<
* @param prefixes - A partial tuple representing the key prefix to filter by.
* @returns An array of keys matching the prefix.
*/
keys<P extends PartialTuple<K>>(
...prefixes: PartialTuple<K> | [Join<PartialTuple<K>, S>]
): Extract<Join<K, S>, Join<P, S>>[] {
keys(...prefixes: PartialTuple<K> | [Join<PartialTuple<K>, S>]): Join<K, S>[] {
const prefix = prefixes.join(this.separator);
const result: string[] = [];

return Object.keys(this.kmap).filter((key) => key.startsWith(prefix)) as Extract<
Join<K, S>,
Join<P, S>
>[];
for (const key of Object.keys(this.kmap)) {
if (!key.startsWith(prefix)) {
continue;
}

result.push(key);
}

return result as Join<K, S>[];
}

/**
Expand All @@ -188,7 +192,54 @@ export class UbiMap<
* @returns An array of values corresponding to the matching keys.
*/
values(...prefixes: PartialTuple<K> | [Join<PartialTuple<K>, S>]): V[] {
return this.keys(...prefixes).map((key) => this.kmap[key]);
const prefix = prefixes.join(this.separator);
const result: V[] = [];

for (const key of Object.keys(this.kmap)) {
if (!key.startsWith(prefix)) {
continue;
}

result.push(this.kmap[key as Join<K, S>]);
}

return result;
}

/**
* Returns an array of key-value pairs whose keys start with the specified prefixes.
*
* @example
*
* ```ts
* const ubimap = new UbiMap<[string, string]>();
*
* ubimap.set('a', 'b', 'value1');
* ubimap.set('a', 'c', 'value2');
* ubimap.set('b', 'c', 'value3');
*
* console.log(ubimap.filter('a b')); // [['a b', 'value1']]
* console.log(ubimap.filter('a', 'b')); // [['a b', 'value1']]
* console.log(ubimap.filter('a')); // [['a b', 'value1'], ['a c', 'value2']]
* console.log(ubimap.filter()); // [['a b', 'value1'], ['a c', 'value2'], ['b c', 'value3']]
* console.log(ubimap.filter(['a', 'b'])); // [['a b', 'value1']]
* ```
*/
filter(...prefixes: PartialTuple<K> | [Join<PartialTuple<K>, S>]): [...K, V][] {
const prefix = prefixes.join(this.separator);
const result: [...K, V][] = [];

for (const [key, value] of Object.entries<V>(this.kmap)) {
if (!key.startsWith(prefix)) {
continue;
}

const keys = key.split(this.separator) as [...K, V];
keys.push(value);
result.push(keys);
}

return result;
}

/** Iterates over all key-value pairs in the map. */
Expand Down
25 changes: 25 additions & 0 deletions packages/ubimap/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,31 @@ describe('UbiMap', () => {
expect(ubimap.getKey('value')).toBe('key1 key2');
});

it('ensures filter works', () => {
const ubimap = new UbiMap<[string, string]>();
ubimap.set('key1', 'key2', 'value1');
ubimap.set('key3', 'key', 'value2');
ubimap.set('key1', 'key3', 'value3');

expect(ubimap.filter('key1')).toEqual([
['key1', 'key2', 'value1'],
['key1', 'key3', 'value3']
]);

expect(ubimap.filter('key1', 'key2')).toEqual([['key1', 'key2', 'value1']]);
expect(ubimap.filter('key1 key2')).toEqual([['key1', 'key2', 'value1']]);

expect(ubimap.filter('key3')).toEqual([['key3', 'key', 'value2']]);

expect(ubimap.filter('key4')).toEqual([]);

expect(ubimap.filter()).toEqual([
['key1', 'key2', 'value1'],
['key3', 'key', 'value2'],
['key1', 'key3', 'value3']
]);
});

it('should return undefined for non-existing value', () => {
const ubimap = new UbiMap<[string, string]>();
expect(ubimap.getKey('nonexistent')).toBeUndefined();
Expand Down

0 comments on commit 6e6f800

Please sign in to comment.