Levenshtein’s distance here is not entirely appropriate, because he will compare character by character for equality. You need to check each color separately, and you want 79 be much closer to 80 than 00 .
The following seems to be much closer to what you want, with minimal changes to your code:
Array.closest = (function () { function dist(s, t) { if (!s.length || !t.length) return 0; return dist(s.slice(2), t.slice(2)) + Math.abs(parseInt(s.slice(0, 2), 16) - parseInt(t.slice(0, 2), 16)); } return function (arr, str) { return arr.sort(function (a, b) { return dist(a, str) - dist(b, str); }); }; }());
Note that this will only give reasonable results if both s and t are hexadecimal sixth hexadecimal characters.
Your code is inefficient because you do not need to sort the entire array to get the closest color. Instead, you should just iterate over the array and track the shortest distance.
For instance:
Array.closest = (function () { function dist(s, t) { if (!s.length || !t.length) return 0; return dist(s.slice(2), t.slice(2)) + Math.abs(parseInt(s.slice(0, 2), 16) - parseInt(t.slice(0, 2), 16)); } return function (arr, str) { var min = 0xffffff; var best, current, i; for (i = 0; i < arr.length; i++) { current = dist(arr[i], str) if (current < min) { min = current best = arr[i]; } } return best; }; }());
Please note that after this change Array.closest() will return a single value, not an array, so you will need to remove [0] further in your code.