diff --git a/lib/binary-search.js b/lib/binary-search.js index d6f898ea..3d8f6003 100644 --- a/lib/binary-search.js +++ b/lib/binary-search.js @@ -32,7 +32,7 @@ function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { // 3. We did not find the exact element, and there is no next-closest // element than the one we are searching for, so we return -1. const mid = Math.floor((aHigh - aLow) / 2) + aLow; - const cmp = aCompare(aNeedle, aHaystack[mid], true); + const cmp = aCompare(aNeedle, aHaystack[mid]); if (cmp === 0) { // Found the element we are looking for. return mid; @@ -95,9 +95,10 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { // We have found either the exact element, or the next-closest element than // the one we are searching for. However, there may be more than one such - // element. Make sure we always return the smallest of these. + // element ONLY IFF we found an exact match. + // Make sure we always return the smallest of these. while (index - 1 >= 0) { - if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { + if (aCompare(aNeedle, aHaystack[index - 1]) !== 0) { break; } --index; diff --git a/test/test-binary-search.js b/test/test-binary-search.js index 5a31aea7..4b62c2f5 100644 --- a/test/test-binary-search.js +++ b/test/test-binary-search.js @@ -94,3 +94,29 @@ exports["test multiple matches at the beginning"] = function(assert) { assert.equal(binarySearch.search(needle, haystack, numberCompare, binarySearch.LEAST_UPPER_BOUND), 0); }; + +exports["test fuzzy match with duplicates in the data at match point"] = function(assert) { + const needle = 2; + const haystack = [1, 1, 5, 5, 5, 5, 13, 21]; + + assert.equal( + binarySearch.search( + needle, + haystack, + numberCompare, + binarySearch.LEAST_UPPER_BOUND + ), + 2 + ); + + assert.equal( + binarySearch.search( + needle, + haystack, + numberCompare, + binarySearch.GREATEST_LOWER_BOUND + ), + 1 + ); +}; +