From 9a858417a857b36f62ed6eb110b914c1330845ba Mon Sep 17 00:00:00 2001 From: Sam Saccone Date: Sat, 1 Jun 2019 13:46:49 -0700 Subject: [PATCH] Implement prefix trimming logic for resolve flow. --- explorer/app/src/resolve/trim.test.ts | 28 ++++++++++++++ explorer/app/src/resolve/trim.ts | 56 +++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 explorer/app/src/resolve/trim.test.ts create mode 100644 explorer/app/src/resolve/trim.ts diff --git a/explorer/app/src/resolve/trim.test.ts b/explorer/app/src/resolve/trim.test.ts new file mode 100644 index 0000000..556f374 --- /dev/null +++ b/explorer/app/src/resolve/trim.test.ts @@ -0,0 +1,28 @@ +import { findTrims } from "./trim"; + +it("finds no trims when no /", () => { + expect(findTrims(["wow"], ["wo"])).toEqual({}); +}); + +it("finds no trims", () => { + expect(findTrims(["wo/ok"], ["../ok"])).toEqual({}); +}); + +it("finds trims", () => { + expect(findTrims(["a/b/ok"], ["b/ok"])).toEqual({ + "a/": 1 + }); + + expect(findTrims(["b/ok"], ["a/b/ok"])).toEqual({ + "a/": 1 + }); +}); + +it("finds multi trims", () => { + expect( + findTrims(["a/b/ok", "nothing", "../a/b.js"], ["b/ok", "a/b.js"]) + ).toEqual({ + "a/": 1, + "../": 1 + }); +}); diff --git a/explorer/app/src/resolve/trim.ts b/explorer/app/src/resolve/trim.ts new file mode 100644 index 0000000..8ceb845 --- /dev/null +++ b/explorer/app/src/resolve/trim.ts @@ -0,0 +1,56 @@ +function generatePrefixList(items: string[]) { + const kk: { [prefix: string]: number } = {}; + + for (const i of items) { + const components = i.split("/"); + let prev = components[0] + "/"; + for (const c of components.slice(1)) { + kk[prev + c] = kk[prev + c] || 0; + kk[prev + c]++; + prev = prev + c + "/"; + } + } + + let prefixItems = []; + for (const k of Object.keys(kk)) { + prefixItems.push({ prefix: k, count: kk[k] }); + } + + return prefixItems.sort((a, b) => b.count - a.count); +} + +/** + * Given two lists of strings find common prefixes that when removed would + * align the two lists of strings. + * @param items + * @param items2 + */ +export function findTrims(items: string[], items2: string[]) { + const prefixList1 = generatePrefixList(items); + const prefixList2 = generatePrefixList(items2); + const recommendedTrims: { [prefix: string]: number } = {}; + for (let i = 0; i < prefixList1.length; i++) { + for (let j = 0; j < prefixList2.length; j++) { + if (prefixList1[i].prefix.length > prefixList2[j].prefix.length) { + const idx = prefixList1[i].prefix.indexOf(prefixList2[j].prefix); + if (idx > -1) { + const str = prefixList1[i].prefix.slice(0, idx); + if (str !== "") { + recommendedTrims[str] = recommendedTrims[str] || 0; + recommendedTrims[str]++; + } + } + } else { + const idx = prefixList2[j].prefix.indexOf(prefixList1[i].prefix); + if (idx > -1) { + const str = prefixList2[j].prefix.slice(0, idx); + if (str !== "") { + recommendedTrims[str] = recommendedTrims[str] || 0; + recommendedTrims[str]++; + } + } + } + } + } + return recommendedTrims; +}