string-similarity
Advanced tools
Comparing version 1.2.2 to 2.0.0
@@ -1,113 +0,55 @@ | ||
var _forEach = require('lodash.foreach'); | ||
var _map = require('lodash.map'); | ||
var _every = require('lodash.every'); | ||
var _maxBy = require('lodash.maxby'); | ||
var _flattenDeep = require('lodash.flattendeep'); | ||
module.exports = { | ||
compareTwoStrings, | ||
findBestMatch | ||
}; | ||
exports.compareTwoStrings = compareTwoStrings; | ||
exports.findBestMatch = findBestMatch; | ||
function compareTwoStrings (str1, str2) { | ||
if (!str1.length && !str2.length) return 1; // if both are empty strings | ||
if (!str1.length || !str2.length) return 0; // if only one is empty string | ||
if (str1.toUpperCase() === str2.toUpperCase()) return 1; // identical | ||
if (str1.length === 1 && str2.length === 1) return 0; // both are 1-letter strings | ||
function compareTwoStrings(str1, str2) { | ||
var result = null; | ||
result = calculateResultIfIdentical(str1, str2); | ||
if (result != null) { | ||
return result; | ||
} | ||
result = calculateResultIfEitherIsEmpty(str1, str2); | ||
if (result != null) { | ||
return result; | ||
} | ||
result = calculateResultIfBothAreSingleCharacter(str1, str2); | ||
if (result != null) { | ||
return result; | ||
} | ||
const pairs1 = wordLetterPairs(str1); | ||
const pairs2 = wordLetterPairs(str2); | ||
const union = pairs1.length + pairs2.length; | ||
let intersection = 0; | ||
pairs1.forEach(pair1 => { | ||
for (let i = 0, pair2; pair2 = pairs2[i]; i++) { | ||
if (pair1 !== pair2) continue; | ||
intersection++; | ||
pairs2.splice(i, 1); | ||
break; | ||
} | ||
}); | ||
return intersection * 2 / union; | ||
} | ||
var pairs1 = wordLetterPairs(str1.toUpperCase()); | ||
var pairs2 = wordLetterPairs(str2.toUpperCase()); | ||
var intersection = 0; | ||
var union = pairs1.length + pairs2.length; | ||
function findBestMatch (mainString, targetStrings) { | ||
if (!areArgsValid(mainString, targetStrings)) throw new Error('Bad arguments: First argument should be a string, second should be an array of strings'); | ||
const ratings = targetStrings.map(target => ({ target, rating: compareTwoStrings(mainString, target) })); | ||
const bestMatch = Array.from(ratings).sort((a, b) => b.rating - a.rating)[0]; | ||
return { ratings, bestMatch }; | ||
} | ||
_forEach(pairs1, function (pair1) { | ||
for(var i = 0; i < pairs2.length; i++) { | ||
var pair2 = pairs2[i]; | ||
if (pair1 === pair2) { | ||
intersection++; | ||
pairs2.splice(i, 1); | ||
break; | ||
} | ||
} | ||
}); | ||
function flattenDeep (arr) { | ||
return Array.isArray(arr) ? arr.reduce((a, b) => a.concat(flattenDeep(b)) , []) : [arr]; | ||
} | ||
return (2.0 * intersection) / union; | ||
function areArgsValid (mainString, targetStrings) { | ||
if (typeof mainString !== 'string') return false; | ||
if (!Array.isArray(targetStrings)) return false; | ||
if (!targetStrings.length) return false; | ||
if (targetStrings.find(s => typeof s !== 'string')) return false; | ||
return true; | ||
} | ||
// private functions --------------------------- | ||
function letterPairs(str) { | ||
var numPairs = str.length - 1; | ||
var pairs = []; | ||
for(var i = 0; i < numPairs; i++) { | ||
pairs[i] = str.substring(i, i + 2); | ||
} | ||
return pairs; | ||
} | ||
function wordLetterPairs(str) { | ||
return _flattenDeep(_map(str.split(' '), letterPairs)); | ||
} | ||
function calculateResultIfIdentical(str1, str2) { | ||
if (str1.toUpperCase() == str2.toUpperCase()) { | ||
return 1; | ||
} | ||
return null; | ||
} | ||
function calculateResultIfBothAreSingleCharacter(str1, str2) { | ||
if (str1.length == 1 && str2.length == 1) { | ||
return 0; | ||
} | ||
} | ||
function calculateResultIfEitherIsEmpty(str1, str2) { | ||
// if both are empty strings | ||
if (str1.length == 0 && str2.length == 0) { | ||
return 1; | ||
} | ||
// if only one is empty string | ||
if ((str1.length + str2.length) > 0 && (str1.length * str2.length) == 0) { | ||
return 0; | ||
} | ||
return null; | ||
} | ||
function letterPairs (str) { | ||
const pairs = []; | ||
for (let i = 0, max = str.length - 1; i < max; i++) pairs[i] = str.substring(i, i + 2); | ||
return pairs; | ||
} | ||
function findBestMatch(mainString, targetStrings) { | ||
if (!areArgsValid(mainString, targetStrings)) { | ||
throw new Error('Bad arguments: First argument should be a string, second should be an array of strings'); | ||
} | ||
var ratings = _map(targetStrings, function (targetString) { | ||
return { | ||
target: targetString, | ||
rating: compareTwoStrings(mainString, targetString) | ||
}; | ||
}); | ||
return { | ||
ratings: ratings, | ||
bestMatch: _maxBy(ratings, 'rating') | ||
}; | ||
// private functions --------------------------- | ||
function areArgsValid(mainString, targetStrings) { | ||
var mainStringIsAString = (typeof mainString === 'string'); | ||
var targetStringsIsAnArrayOfStrings = Array.isArray(targetStrings) && | ||
targetStrings.length > 0 && | ||
_every(targetStrings, function (targetString) { | ||
return (typeof targetString === 'string'); | ||
}); | ||
return mainStringIsAString && targetStringsIsAnArrayOfStrings; | ||
} | ||
function wordLetterPairs (str) { | ||
const pairs = str.toUpperCase().split(' ').map(letterPairs); | ||
return flattenDeep(pairs); | ||
} |
{ | ||
"name": "string-similarity", | ||
"version": "1.2.2", | ||
"version": "2.0.0", | ||
"description": "Finds degree of similarity between strings, based on Dice's Coefficient, which is mostly better than Levenshtein distance.", | ||
@@ -33,10 +33,3 @@ "main": "compare-strings.js", | ||
"jasmine": "^3.2.0" | ||
}, | ||
"dependencies": { | ||
"lodash.every": "^4.6.0", | ||
"lodash.flattendeep": "^4.4.0", | ||
"lodash.foreach": "^4.5.0", | ||
"lodash.map": "^4.6.0", | ||
"lodash.maxby": "^4.6.0" | ||
} | ||
} |
@@ -6,2 +6,18 @@ string-similarity | ||
## Table of Contents | ||
* [Usage](#usage) | ||
* [API](#api) | ||
* [compareTwoStrings(string1, string2)](#comparetwostringsstring1-string2) | ||
* [Arguments](#arguments) | ||
* [Returns](#returns) | ||
* [Examples](#examples) | ||
* [findBestMatch(mainString, targetStrings)](#findbestmatchmainstring-targetstrings) | ||
* [Arguments](#arguments-1) | ||
* [Returns](#returns-1) | ||
* [Examples](#examples-1) | ||
* [Release Notes](#release-notes) | ||
* [2.0.0](#200) | ||
## Usage | ||
@@ -93,3 +109,10 @@ Install using: | ||
## Release Notes | ||
### 2.0.0 | ||
* Removed production dependencies | ||
* Updated to ES6 (this breaks backward-compatibility for pre-ES6 apps) | ||
![Build status](https://codeship.com/projects/2aa453d0-0959-0134-8a76-4abcb29fe9b4/status?branch=master) | ||
[![Known Vulnerabilities](https://snyk.io/test/github/aceakash/string-similarity/badge.svg)](https://snyk.io/test/github/aceakash/string-similarity) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
7729
0
4
117
1
48
- Removedlodash.every@^4.6.0
- Removedlodash.flattendeep@^4.4.0
- Removedlodash.foreach@^4.5.0
- Removedlodash.map@^4.6.0
- Removedlodash.maxby@^4.6.0
- Removedlodash.every@4.6.0(transitive)
- Removedlodash.flattendeep@4.4.0(transitive)
- Removedlodash.foreach@4.5.0(transitive)
- Removedlodash.map@4.6.0(transitive)
- Removedlodash.maxby@4.6.0(transitive)