6

I need to sort an array of values.

var arr = [0.3, 0.76, 0.98, 1.12, 1.36, 1.9];

by which value is closest to 1, which would (in the above example) result in:

[0.98, 1.12, 0.76, 1.36, 0.3, 1.9];

I know that by using a custom sort function.

arr.sort(function(a, b){
    return b - a;
});

i can take control of how sort() works, however, i do not understand how i would design that custom function so that it would work in the desired way.

Perhaps someone can enlighten me.

SquareCat
  • 5,699
  • 9
  • 41
  • 75

3 Answers3

19

Just check their distance from 1.

arr.sort(function(a, b){
    return Math.abs(1-a) - Math.abs(1-b);
});

Just to elaborate, it calculates the distance of two numbers from 1, i.e. for

  • a=-10 and b=4, the distances are 11 and 3 respectively. The function returns a positive number, so 4 comes before -10 in the sorted array.
  • For a=-1 and b=4, the distances would be 2 and 3, the function returns a negative number so -1 comes before 4 in the array.

As requested in the comments, the below adaptation would give preference to values below 1.

arr.sort(function(a, b){
    if(a<1 && b>=1){return -1;}
    if(a>=1 && b<1){return 1;}
    return (Math.abs(1-a) - Math.abs(1-b));
});
BatScream
  • 19,260
  • 4
  • 52
  • 68
  • Could you by any chance elaborate on this and show how it could be adapted, so that it puts a preference to values which are smaller than 1 rather than those that are greater? – SquareCat Nov 14 '14 at 04:14
1

If you want numbers less than 1 to be biased to sort lower that equally distant numbers greater than 1, test if the delta is equal and modify one of the values if it is:

var arr = [1.02, 0.3, 0.76, 0.98, 1.12, 1.36, 1.9, 1.24];

// Unbiased
arr.sort(function(a, b){
    return Math.abs(1-a) - Math.abs(1-b);
});

console.log('unbiased: ' + arr); // unbiased: 1.02,0.98,1.12,0.76,1.24,1.36,0.3,1.9

var arr = [1.02, 0.3, 0.76, 0.98, 1.12, 1.36, 1.9, 1.24];

// Biased so numbers less than 1 sort higher than those greater than 1
// where their difference from 1 is equal
arr.sort(function(a, b) {
  var da = 1 - a;
  var db = 1 - b;

  da -= da < 0? 1e-14 : 0;
  db -= db < 0? 1e-14 : 0;

  return Math.abs(da) - Math.abs(db);
});

console.log('biased: ' + arr); // biased: 0.98,1.02,1.12,0.76,1.24,1.36,0.3,1.9
RobG
  • 142,382
  • 31
  • 172
  • 209
0

Just to update @batscream answer with arrow function implementation

arr = arr.sort((a, b) => {
    return Math.abs(1-a) - Math.abs(1-b);
});

var arr = [0.3, 0.76, 0.98, 1.12, 1.36, 1.9];
arr = arr.sort((a, b) => {
    return Math.abs(1-a) - Math.abs(1-b);
});
console.log(arr);

Reference : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Umair Mohammad
  • 4,489
  • 2
  • 20
  • 34