similarity and string-similarity are both JavaScript libraries designed to calculate how alike two strings are, but they use fundamentally different algorithms suited for different problems. similarity implements the Levenshtein distance algorithm, which counts the minimum number of single-character edits (insertions, deletions, or substitutions) required to change one string into another. It is ideal for typo correction and measuring exact character-level differences. string-similarity, on the other hand, uses the Dice Coefficient based on bigrams (pairs of characters). This approach is better at matching strings that have the same characters in a similar order but might have extra noise or slight reordering, making it popular for fuzzy search and record linkage where strict edit distance is too rigid.
When implementing search bars, deduplication logic, or typo tolerance in your application, picking the right string comparison library is critical. similarity and string-similarity look similar at a glance, but they solve different problems using distinct mathematical approaches. One counts edits; the other measures overlap. Let's dig into how they work and when to use each.
similarity relies on the Levenshtein Distance algorithm.
import similarity from 'similarity';
// Comparing 'kitten' and 'sitting'
const distance = similarity('kitten', 'sitting');
console.log(distance);
// Output: 3
// Explanation: kitten -> sitten (1) -> sittin (2) -> sitting (3)
string-similarity uses the Dice Coefficient based on bigrams.
import stringSimilarity from 'string-similarity';
// Comparing 'kitten' and 'sitting'
const score = stringSimilarity.compareTwoStrings('kitten', 'sitting');
console.log(score);
// Output: ~0.57
// Explanation: Measures the ratio of shared character pairs, not edit steps.
The way these libraries return data dictates how you write your conditional logic.
similarity returns a raw count.
import similarity from 'similarity';
const str1 = 'apple';
const str2 = 'aple'; // Missing 'p'
const distance = similarity(str1, str2);
const isClose = distance <= 1; // Allow 1 typo
console.log(`Distance: ${distance}, Is Close: ${isClose}`);
// Output: Distance: 1, Is Close: true
string-similarity returns a normalized score.
import stringSimilarity from 'string-similarity';
const str1 = 'apple';
const str2 = 'aple';
const score = stringSimilarity.compareTwoStrings(str1, str2);
const isClose = score >= 0.8; // Accept 80% similarity
console.log(`Score: ${score}, Is Close: ${isClose}`);
// Output: Score: ~0.89, Is Close: true
A common task is finding the best match for a user's query from a list of options.
similarity requires you to write the looping logic yourself.
import similarity from 'similarity';
const query = 'ninja';
const candidates = ['turtle', 'ninjas', 'ping', 'ninja-turtle'];
const bestMatch = candidates.reduce((best, current) => {
const currentDist = similarity(query, current);
const bestDist = similarity(query, best);
// Lower distance is better
return currentDist < bestDist ? current : best;
});
console.log(bestMatch);
// Output: 'ninjas' (Distance 1)
string-similarity provides a dedicated helper for this exact scenario.
findBestMatch, which returns a ranked list of results with scores.import stringSimilarity from 'string-similarity';
const query = 'ninja';
const candidates = ['turtle', 'ninjas', 'ping', 'ninja-turtle'];
const match = stringSimilarity.findBestMatch(query, candidates);
console.log(match.bestMatch.target);
// Output: 'ninjas'
console.log(match.ratings);
// Output: Sorted array of all candidates with their scores
Performance characteristics differ based on string length and content.
similarity can become slow on very long strings.
import similarity from 'similarity';
// Swapping words creates a large distance
const s1 = 'the quick brown fox';
const s2 = 'the brown quick fox';
console.log(similarity(s1, s2));
// Output: High number (many edits needed to swap words)
string-similarity generally scales better for fuzzy matching tasks.
import stringSimilarity from 'string-similarity';
// Swapping words retains a decent score
const s1 = 'the quick brown fox';
const s2 = 'the brown quick fox';
console.log(stringSimilarity.compareTwoStrings(s1, s2));
// Output: Moderate/High score (many bigrams still match)
If you are building a search bar that needs to fix small typos like "iphon" to "iphone":
similarity if you want strict control over how many keystrokes are allowed.string-similarity if you want a quick implementation with a confidence threshold.// Using string-similarity for quick spell check
import stringSimilarity from 'string-similarity';
function correctSpell(input, dictionary) {
const match = stringSimilarity.findBestMatch(input, dictionary);
// Only correct if confidence is high
return match.bestMatch.rating > 0.7 ? match.bestMatch.target : input;
}
If you are merging user lists and need to find duplicates like "John Smith" vs "Jon Smith":
string-similarity. The Dice coefficient handles the transposition of 'h' and missing 'h' gracefully, providing a clear percentage match to set a cutoff.// Using string-similarity for deduplication
import stringSimilarity from 'string-similarity';
const isNewEntryUnique = (newName, existingList) => {
return !existingList.some(existing => {
return stringSimilarity.compareTwoStrings(newName, existing) > 0.85;
});
};
| Feature | similarity | string-similarity |
|---|---|---|
| Algorithm | Levenshtein Distance | Dice Coefficient (Bigrams) |
| Output | Integer (Edit Count) | Float (0.0 to 1.0 Score) |
| Best Match Logic | Manual Implementation Required | Built-in findBestMatch |
| Ideal For | Spell checkers, diff tools, strict validation | Fuzzy search, record linkage, autocomplete |
| Sensitivity | Sensitive to character order | Tolerant of reordering and noise |
| Interpretation | Lower is better | Higher is better |
Choose similarity if your use case revolves around editing. If you need to tell a user "you are 2 characters away from a valid password" or build a strict diff tool, the Levenshtein distance is the industry standard. It provides precise, actionable data about character differences.
Choose string-similarity if your use case revolves around searching. If you are building a fuzzy search bar, matching customer names across databases, or suggesting tags, the Dice Coefficient offers a more intuitive "confidence score." The built-in findBestMatch helper also significantly reduces boilerplate code, making it the pragmatic choice for most frontend search features.
Choose similarity when you need to measure the exact 'cost' of transforming one string into another, such as in spell-checkers or password strength analyzers. It is the right tool when the number of specific character edits matters more than general visual resemblance. Since it returns a raw distance count (lower is better), it fits well in scenarios where you define a maximum allowable edit threshold. Avoid this if you need a normalized 0-to-1 score out of the box or if your data contains significant rearranging of words.
Choose string-similarity when building fuzzy search features, autocomplete suggestions, or deduplication tools where users might type phrases with extra spaces or slight word swaps. Its Dice Coefficient algorithm returns a normalized score between 0 and 1, making it easier to set confidence thresholds without complex math. It handles longer strings and minor reordering better than Levenshtein distance. Do not use this if you require strict character-perfect validation or need to know the exact number of edits required to fix a string.
How similar are these two strings?
npm:
npm install similarity
var similarity = require('similarity')
similarity('food', 'food') // 1
similarity('food', 'fool') // 0.75
similarity('ding', 'plow') // 0
similarity('chicken', 'chick') // 0.714285714
similarity('ES6-Shim', 'es6 shim') // 0.875 (case insensitive)
similarity('ES6-Shim', 'es6 shim', {sensitive: true}) // 0.5 (case sensitive)
similarity(left, right[, options])Get the similarity (number) between two values (strings),
where 0 is dissimilar, and 1 is equal.
options.sensitive (boolean, default: false)
— Turn on (true) to treat casing differences as differencesUsage: similarity [options] <word> <word>
How similar are these two strings?
Options:
-h, --help output usage information
-v, --version output version number
-s, --sensitive be sensitive to casing differences
Usage:
# output similarity
$ similarity sitting kitten
0.5714285714285714
$ similarity saturday sunday
0.625
Note: This module uses Levenshtein distance to measure similarity, but there are many other algorithms for string comparison. Here are a few:
clj-fuzzy
— Handy collection of algorithms dealing with fuzzy strings and phoneticsnatural
— General natural language facilities for nodestring-similarity
— Finds degree of similarity between two strings, based on Dice’s
coefficientdice-coefficient
— Sørensen–Dice coefficientjaro-winkler
— The Jaro-Winkler distance metric