First title to compare.
Second title to compare.
True if titles are identical except for article presence/absence.
export function isDifferenceOnlyArticles(
leftTitle: string,
rightTitle: string,
): boolean {
const articles = new Set(["a", "an", "the"]);
// Normalize both titles (now uses cache)
const leftWords = normalizeForMatching(leftTitle)
.split(/\s+/)
.filter((word) => word.length > 0);
const rightWords = normalizeForMatching(rightTitle)
.split(/\s+/)
.filter((word) => word.length > 0);
console.debug(
`[MangaSearchService] 🔍 Checking article difference between "${leftTitle}" and "${rightTitle}"`,
);
console.debug(
`[MangaSearchService] Normalized: ["${leftWords.join('", "')}" vs ["${rightWords.join('", "')}"]`,
);
// Find the longer and shorter word arrays
const [longer, shorter] =
leftWords.length >= rightWords.length
? [leftWords, rightWords]
: [rightWords, leftWords];
// If they have the same number of words, they're not article-different
if (longer.length === shorter.length) {
console.debug(`[MangaSearchService] Same length, not article difference`);
return false;
}
// Remove all articles from both arrays and compare
const longerWithoutArticles = longer.filter((word) => !articles.has(word));
const shorterWithoutArticles = shorter.filter((word) => !articles.has(word));
console.debug(
`[MangaSearchService] Without articles: ["${longerWithoutArticles.join('", "')}" vs ["${shorterWithoutArticles.join('", "')}"]`,
);
// If after removing articles, they're identical, then the difference was only articles
const isArticleOnly =
longerWithoutArticles.length === shorterWithoutArticles.length &&
longerWithoutArticles.every(
(word, index) => word === shorterWithoutArticles[index],
);
console.debug(
`[MangaSearchService] Article-only difference: ${isArticleOnly}`,
);
return isArticleOnly;
}
Checks if the difference between two titles is solely due to articles (a, an, the). Useful for matching titles that differ only in article usage. Uses cache.