This repository has been archived by the owner on May 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 129
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14 from tborychowski/master
es6-ify; remove dependencies
- Loading branch information
Showing
2 changed files
with
48 additions
and
112 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,113 +1,56 @@ | ||
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'); | ||
|
||
exports.compareTwoStrings = compareTwoStrings; | ||
exports.findBestMatch = findBestMatch; | ||
|
||
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; | ||
} | ||
|
||
var pairs1 = wordLetterPairs(str1.toUpperCase()); | ||
var pairs2 = wordLetterPairs(str2.toUpperCase()); | ||
var intersection = 0; | ||
var union = pairs1.length + pairs2.length; | ||
|
||
_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; | ||
} | ||
} | ||
}); | ||
|
||
return (2.0 * intersection) / union; | ||
|
||
// 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; | ||
} | ||
function flattenDeep (arr) { | ||
return Array.isArray(arr) ? arr.reduce((a, b) => a.concat(flattenDeep(b)) , []) : [arr]; | ||
} | ||
|
||
// if only one is empty string | ||
if ((str1.length + str2.length) > 0 && (str1.length * str2.length) == 0) { | ||
return 0; | ||
} | ||
return null; | ||
} | ||
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; | ||
} | ||
|
||
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) | ||
}; | ||
}); | ||
function wordLetterPairs (str) { | ||
const pairs = str.toUpperCase().split(' ').map(letterPairs); | ||
return flattenDeep(pairs); | ||
} | ||
|
||
return { | ||
ratings: ratings, | ||
bestMatch: _maxBy(ratings, 'rating') | ||
}; | ||
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 | ||
|
||
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; | ||
} | ||
|
||
// private functions --------------------------- | ||
function areArgsValid(mainString, targetStrings) { | ||
var mainStringIsAString = (typeof mainString === 'string'); | ||
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 }; | ||
} | ||
|
||
var targetStringsIsAnArrayOfStrings = Array.isArray(targetStrings) && | ||
targetStrings.length > 0 && | ||
_every(targetStrings, function (targetString) { | ||
return (typeof targetString === 'string'); | ||
}); | ||
|
||
return mainStringIsAString && targetStringsIsAnArrayOfStrings; | ||
} | ||
} | ||
module.exports = { | ||
compareTwoStrings, | ||
findBestMatch | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters