Last active
July 14, 2017 14:09
-
-
Save joewright/f89bbdacff330de7d1360858ce953275 to your computer and use it in GitHub Desktop.
Find closest matches in an array
This file contains hidden or 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
function findNearestMatches(data, target, windowSize) { | |
/* | |
* Find [windowSize] items closest to [target] value | |
* | |
* var arr = [0,1,2,3,4,5]; | |
* findNearestMatches(arr, 2, 3) | |
* -> [1,2,3] | |
* findNearestMatches(arr, -5, 4) | |
* -> [0,1,2.3] | |
*/ | |
if (data.length < windowSize) { | |
return data; | |
} | |
var results = []; | |
var middleIndex = Math.floor(windowSize / 2); | |
var matchIndex = data.indexOf(target); | |
var firstIndex; | |
if (matchIndex === -1) { | |
// get first index of an item > the target | |
for (var z = 0; z < data.length; z++) { | |
if (data[z] > target || z === data.length - 1) { | |
matchIndex = z; | |
break; | |
} | |
} | |
} | |
// start from the matched index - # of items to put it in the middle | |
for (var x = (matchIndex - middleIndex); x <= matchIndex; x++) { | |
if (data[x]) { | |
if (firstIndex === undefined) { | |
firstIndex = x; | |
} | |
results.push(data[x]); | |
} | |
} | |
// add items to the right | |
var lastItemIndex = matchIndex + (windowSize - results.length) + 1; | |
for (var i = (matchIndex + 1); i < lastItemIndex; i++) { | |
if (data[i]) { | |
results.push(data[i]); | |
} | |
} | |
// add some more on the left if it's a later match | |
if (results.length < windowSize) { | |
var diff = windowSize - results.length; | |
for (var y = 1; y <= diff; y++) { | |
if (data[firstIndex - y]) { | |
results.push(data[firstIndex - y]); | |
} | |
} | |
} | |
return results.sort(); | |
} | |
/* | |
* test it with mocha | |
*/ | |
var assert = require('assert'); | |
var start_dates = [ | |
'2017-07-23T09:30:00', | |
'2017-07-23T10:30:00', | |
'2017-07-23T11:30:00', | |
'2017-07-23T11:30:00', | |
'2017-07-23T12:30:00', | |
'2017-07-23T13:30:00', | |
'2017-07-23T14:30:00', | |
'2017-07-23T17:30:00', | |
'2017-07-23T18:30:00', | |
'2017-07-23T19:30:00', | |
'2017-07-23T20:30:00' | |
]; | |
var target = '2017-07-23T12:15:00'; | |
describe('findNearestMatches', function() { | |
it('returns the whole list when windowSize is larger than dataset length', function() { | |
var sorted = findNearestMatches(start_dates, target, 90); | |
assert.equal(sorted, start_dates); | |
}); | |
it('can have a windowSize of 1', function() { | |
var sorted = findNearestMatches(start_dates, target, 1); | |
assert.equal(sorted.length, 1); | |
}); | |
it('returns a list the same length as windowSize', function() { | |
var sorted = findNearestMatches(start_dates, target, 5); | |
assert.equal(sorted.length, 5); | |
var sorted2 = findNearestMatches(start_dates, target, 3); | |
assert.equal(sorted2.length, 3); | |
var sorted3 = findNearestMatches(start_dates, target, 4); | |
assert.equal(sorted3.length, 4); | |
}); | |
it('puts matching goal in the middle', function() { | |
var target2 = '2017-07-23T12:30:00'; | |
var sorted = findNearestMatches(start_dates, target2, 5); | |
var sortedIndex = sorted.indexOf(target2); | |
// in the array | |
assert.notEqual(sortedIndex, -1); | |
// in the middle | |
assert.equal(Math.floor(sorted.length / 2), sortedIndex); | |
// wasn't in the middle of original array | |
assert.notEqual(sortedIndex, start_dates.indexOf(target2)); | |
}); | |
it('matches an item at the end; still returns windowSize length', function() { | |
var target2 = '2017-07-23T20:30:00'; | |
var sorted = findNearestMatches(start_dates, target2, 5); | |
assert.equal(sorted.length, 5); | |
}); | |
it('matches an item at the beginning; still returns windowSize length', function() { | |
var target2 = '2017-06-23T20:30:00'; | |
var sorted = findNearestMatches(start_dates, target2, 5); | |
assert.equal(sorted.length, 5); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment