From d90f01b99ecac659e810519bbf68e290af43bc5d Mon Sep 17 00:00:00 2001 From: Alexandre Rousseau Date: Mon, 29 Apr 2024 23:24:50 +0200 Subject: [PATCH] perf: improve list tags performances --- src/List.context.test.ts | 12 ++++++++++ src/List.extensions.test.ts | 17 ++++++++++++++ src/List.projects.test.ts | 12 ++++++++++ src/List.ts | 44 +++++++++++++++++++++++-------------- 4 files changed, 69 insertions(+), 16 deletions(-) create mode 100644 src/List.context.test.ts create mode 100644 src/List.extensions.test.ts create mode 100644 src/List.projects.test.ts diff --git a/src/List.context.test.ts b/src/List.context.test.ts new file mode 100644 index 0000000..afde050 --- /dev/null +++ b/src/List.context.test.ts @@ -0,0 +1,12 @@ +import test from 'ava'; +import { List } from './List'; + +test('context › get contexts', (t) => { + const list = new List('first item @context-1\nsecond item @context-2'); + t.deepEqual(list.contexts(), ['context-1', 'context-2']); +}); + +test('context › deduplicate', (t) => { + const list = new List('first item @context-1\nsecond item @context-1'); + t.deepEqual(list.contexts(), ['context-1']); +}); diff --git a/src/List.extensions.test.ts b/src/List.extensions.test.ts new file mode 100644 index 0000000..3507af3 --- /dev/null +++ b/src/List.extensions.test.ts @@ -0,0 +1,17 @@ +import test from 'ava'; +import { List } from './List'; + +test('extensions › get extensions', (t) => { + const list = new List('first item ext-1:value-1\nsecond item ext-2:value-2'); + t.deepEqual(list.extensions(), { + 'ext-1': ['value-1'], + 'ext-2': ['value-2'], + }); +}); + +test('extensions › deduplicate', (t) => { + const list = new List('first item ext-1:value-1\nsecond item ext-1:value-1 ext-1:value-2'); + t.deepEqual(list.extensions(), { + 'ext-1': ['value-1', 'value-2'], + }); +}); diff --git a/src/List.projects.test.ts b/src/List.projects.test.ts new file mode 100644 index 0000000..bc047bb --- /dev/null +++ b/src/List.projects.test.ts @@ -0,0 +1,12 @@ +import test from 'ava'; +import { List } from './List'; + +test('projects › get projects', (t) => { + const list = new List('first item +project-1\nsecond item +project-2'); + t.deepEqual(list.projects(), ['project-1', 'project-2']); +}); + +test('projects › deduplicate', (t) => { + const list = new List('first item +project-1\nsecond item +project-1'); + t.deepEqual(list.projects(), ['project-1']); +}); diff --git a/src/List.ts b/src/List.ts index db4aebf..ddc7622 100644 --- a/src/List.ts +++ b/src/List.ts @@ -62,29 +62,41 @@ export class List { } projects(): string[] { - return [ - ...new Set(this.#items.map((item) => item.projects()).reduce((p, n) => [...p, ...n], [])), - ]; + const projects = new Set(); + + for (const item of this.#items) { + item.projects().forEach((p) => projects.add(p)); + } + + return [...projects]; } contexts(): string[] { - return [ - ...new Set(this.#items.map((item) => item.contexts()).reduce((p, n) => [...p, ...n], [])), - ]; + const context = new Set(); + + for (const item of this.#items) { + item.contexts().forEach((c) => context.add(c)); + } + + return [...context]; } extensions(): KeysForExtensions { - const ret: KeysForExtensions = {}; - - this.#items.forEach((item) => { - item.extensions().forEach((ext) => { - const values = ret[ext.key] || []; - values.push(ext.value); - ret[ext.key] = [...new Set(values)]; - }); - }); + const extensionsSets = this.#items + .flatMap((i) => i.extensions()) + .reduce>>((acc, { key, value }) => { + if (acc[key] === undefined) { + acc[key] = new Set([value]); + } else { + acc[key].add(value); + } + return acc; + }, {}); - return ret; + return Object.entries(extensionsSets).reduce((acc, [key, value]) => { + acc[key] = [...value]; + return acc; + }, {}); } filter(input: ListFilter): ListItem[] {