Skip to content

Commit

Permalink
fix: remove external depedency for string similarity calculation (#9944)
Browse files Browse the repository at this point in the history
* fix: remove depedency for edit distance

* test: ut
  • Loading branch information
jayzhang authored Sep 14, 2023
1 parent 3ea9bb2 commit 60d5b8a
Show file tree
Hide file tree
Showing 5 changed files with 341 additions and 78 deletions.
1 change: 0 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@
"figures": "^3.2.0",
"fs-extra": "^9.1.0",
"lodash": "^4.17.21",
"natural": "^6.7.2",
"node-machine-id": "^1.1.12",
"open": "^8.2.1",
"semver": "^7.5.4",
Expand Down
7 changes: 3 additions & 4 deletions packages/cli/src/commands/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,9 @@ import {
import CliTelemetry from "../telemetry/cliTelemetry";
import { TelemetryComponentType, TelemetryProperty } from "../telemetry/cliTelemetryEvents";
import UI from "../userInteraction";
import { CliConfigOptions, UserSettings } from "../userSetttings";
import { getSystemInputs } from "../utils";
import { CliConfigOptions } from "../userSetttings";
import { editDistance, getSystemInputs } from "../utils";
import { helper } from "./helper";
import natural from "natural";

class CLIEngine {
/**
Expand Down Expand Up @@ -280,7 +279,7 @@ class CLIEngine {
let mini = token.length;
let mostSimilarCommand: CLICommand | undefined = undefined;
for (const cmd of context.command.commands || []) {
const d = natural.LevenshteinDistance(token, cmd.name);
const d = editDistance(token, cmd.name);
if (d < mini && d <= 2) {
mini = d;
mostSimilarCommand = cmd;
Expand Down
30 changes: 30 additions & 0 deletions packages/cli/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,33 @@ export async function getTemplates(): Promise<Sample[]> {
});
return samples;
}

export function editDistance(s1: string, s2: string): number {
const len1 = s1.length;
const len2 = s2.length;

// Create a 2D array to store the edit distances
const dp: number[][] = new Array(len1 + 1).fill(0).map(() => new Array(len2 + 1).fill(0));

// Initialize the first row and column
for (let i = 0; i <= len1; i++) {
dp[i][0] = i;
}
for (let j = 0; j <= len2; j++) {
dp[0][j] = j;
}

// Calculate the edit distance using dynamic programming
for (let i = 1; i <= len1; i++) {
for (let j = 1; j <= len2; j++) {
const cost = s1[i - 1] === s2[j - 1] ? 0 : 1;
dp[i][j] = Math.min(
dp[i - 1][j] + 1, // Deletion
dp[i][j - 1] + 1, // Insertion
dp[i - 1][j - 1] + cost // Substitution
);
}
}

return dp[len1][len2];
}
26 changes: 26 additions & 0 deletions packages/cli/tests/unit/utils.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import activate from "../../src/activate";
import AzureAccountManager from "../../src/commonlib/azureLogin";
import { UserSettings } from "../../src/userSetttings";
import {
editDistance,
flattenNodes,
getColorizedString,
getSettingsVersion,
Expand Down Expand Up @@ -416,3 +417,28 @@ describe("activate", async () => {
}
});
});

describe("editDistance", async () => {
it("happy", async () => {
{
const d = editDistance("a", "b");
expect(d).equals(1);
}
{
const d = editDistance("abc", "abd");
expect(d).equals(1);
}
{
const d = editDistance("abc", "aabbc");
expect(d).equals(2);
}
{
const d = editDistance("", "abc");
expect(d).equals(3);
}
{
const d = editDistance("abc", "");
expect(d).equals(3);
}
});
});
Loading

0 comments on commit 60d5b8a

Please sign in to comment.