Skip to content

Instantly share code, notes, and snippets.

@joewright
Last active July 14, 2017 14:09
Show Gist options
  • Save joewright/f89bbdacff330de7d1360858ce953275 to your computer and use it in GitHub Desktop.
Save joewright/f89bbdacff330de7d1360858ce953275 to your computer and use it in GitHub Desktop.
Find closest matches in an array
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