69 lines
2.2 KiB
JavaScript
69 lines
2.2 KiB
JavaScript
/**
|
|
* Calculate Levenshtein distance between two strings
|
|
* @param {string} str1 - First string
|
|
* @param {string} str2 - Second string
|
|
* @returns {number} - Edit distance
|
|
*/
|
|
function levenshteinDistance(str1, str2) {
|
|
const len1 = str1.length;
|
|
const len2 = str2.length;
|
|
const matrix = Array(len1 + 1).fill(null).map(() => Array(len2 + 1).fill(0));
|
|
|
|
for (let i = 0; i <= len1; i++) matrix[i][0] = i;
|
|
for (let j = 0; j <= len2; j++) matrix[0][j] = j;
|
|
|
|
for (let i = 1; i <= len1; i++) {
|
|
for (let j = 1; j <= len2; j++) {
|
|
const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;
|
|
matrix[i][j] = Math.min(
|
|
matrix[i - 1][j] + 1, // deletion
|
|
matrix[i][j - 1] + 1, // insertion
|
|
matrix[i - 1][j - 1] + cost // substitution
|
|
);
|
|
}
|
|
}
|
|
|
|
return matrix[len1][len2];
|
|
}
|
|
|
|
/**
|
|
* Calculate similarity percentage between two strings (0-100%)
|
|
* @param {string} str1 - First string
|
|
* @param {string} str2 - Second string
|
|
* @returns {number} - Similarity percentage
|
|
*/
|
|
export function calculateSimilarity(str1, str2) {
|
|
const lower1 = str1.toLowerCase().trim();
|
|
const lower2 = str2.toLowerCase().trim();
|
|
|
|
if (lower1 === lower2) return 100;
|
|
if (lower1.length === 0 || lower2.length === 0) return 0;
|
|
|
|
const distance = levenshteinDistance(lower1, lower2);
|
|
const maxLength = Math.max(lower1.length, lower2.length);
|
|
const similarity = ((maxLength - distance) / maxLength) * 100;
|
|
|
|
return Math.round(similarity);
|
|
}
|
|
|
|
/**
|
|
* Find items with similarity >= threshold
|
|
* @param {string} inputName - Item name to check
|
|
* @param {Array} existingItems - Array of existing items with item_name property
|
|
* @param {number} threshold - Minimum similarity percentage (default 80)
|
|
* @returns {Array} - Array of similar items sorted by similarity
|
|
*/
|
|
export function findSimilarItems(inputName, existingItems, threshold = 80) {
|
|
const similar = [];
|
|
|
|
for (const item of existingItems) {
|
|
const similarity = calculateSimilarity(inputName, item.item_name);
|
|
if (similarity >= threshold && similarity < 100) {
|
|
similar.push({ ...item, similarity });
|
|
}
|
|
}
|
|
|
|
// Sort by similarity descending
|
|
return similar.sort((a, b) => b.similarity - a.similarity);
|
|
}
|