What's the logic behind the SomeArray.sort ( f

2019-08-07 16:47发布

问题:

var array = [3,9,23,76,1,54,21,12,0,9,2];
var shuffled = array.sort(function() {return 0.5 - Math.random()});
console.log(shuffled);  

I'm aware of the results, and also satified with them.

The code above returns a shuffled order of the elements of my array.

I'm puzzled by why it results in that output.

What's the point of the function inside of the .sort and how does it contribute to the output?

回答1:

The function actually takes two arguments, which are 2 items from the array. The purpose is to compare these elements and return a number.
If the number is positive, the second item should be before the first item.
If the number is 0 or negative, the second item should be after the first item.

[0,1].sort(function(a,b){return  1;}); // [1, 0], reverses order
[0,1].sort(function(a,b){return  0;}); // [0, 1], does nothing
[0,1].sort(function(a,b){return -1;}); // [0, 1], does nothing 

In each case of the example above, a === 0 and b === 1.


Edit for step by step output

To see step-by-step what is happening with an ascending sort on [1,3,2,4,4,0], one can write a function which logs exactly what happens each step

arr = [1,3,2,4,4,0];
arr.sort(function(a,b){ // ascending order sort
    var result = a-b,
    str = '';
    if(result > 0) str = 'so swapping';
    else if(result === 0) str = 'so ignoring'
    else str = 'so continuing';
    console.log('with [ '+arr.join(', ')+' ]','comparing',a,'to',b,'resulting in',result, str);
    return result;
});
console.log('resulting in [ '+arr.join(', ')+' ]');

which outputs

with [ 1, 3, 2, 4, 4, 0 ] comparing 1 to 3 resulting in -2 so continuing
with [ 1, 3, 2, 4, 4, 0 ] comparing 3 to 2 resulting in 1 so swapping
with [ 1, 3, 3, 4, 4, 0 ] comparing 1 to 2 resulting in -1 so continuing
with [ 1, 2, 3, 4, 4, 0 ] comparing 3 to 4 resulting in -1 so continuing
with [ 1, 2, 3, 4, 4, 0 ] comparing 4 to 4 resulting in 0 so ignoring
with [ 1, 2, 3, 4, 4, 0 ] comparing 4 to 0 resulting in 4 so swapping
with [ 1, 2, 3, 4, 4, 4 ] comparing 4 to 0 resulting in 4 so swapping
with [ 1, 2, 3, 4, 4, 4 ] comparing 3 to 0 resulting in 3 so swapping
with [ 1, 2, 3, 3, 4, 4 ] comparing 2 to 0 resulting in 2 so swapping
with [ 1, 2, 2, 3, 4, 4 ] comparing 1 to 0 resulting in 1 so swapping
resulting in [ 0, 1, 2, 3, 4, 4 ]

For completeness, probability table for shuffle algorithm in original question (estimates, based on 500,000 trials for each index), X is starting index

 x     0     1     2     3     4     5     6     7     8     9    10
 0 |  8.0,  8.0,  6.2,  6.6,  9.2, 10.8,  9.3,  6.6,  6.2,  9.7, 18.8
 1 |  4.5,  4.6,  7.8, 12.2, 16.9, 12.9, 11.4, 10.7,  8.7,  6.1,  3.6
 2 | 15.5, 15.5, 10.3,  5.9,  3.7,  3.8,  5.7,  8.3, 10.6, 11.7,  8.5
 3 | 10.4, 10.3, 13.4, 10.2,  7.0,  6.5,  7.8,  9.4,  9.7,  8.8,  6.0
 4 |  6.4,  6.3, 10.7, 15.4, 11.4,  9.5,  9.6,  9.9,  8.9,  6.9,  4.4
 5 | 16.1, 16.1, 10.9,  7.7,  7.4,  7.6,  6.2,  4.4,  4.1,  6.5, 12.5
 6 |  4.7,  4.7,  7.1,  9.7, 12.6, 16.3, 13.6, 11.9,  9.2,  6.1,  3.6
 7 |  6.0,  6.0,  7.7,  8.9,  9.4, 10.9, 14.0, 13.6, 11.2,  7.4,  4.3
 8 |  8.4,  8.3,  9.1,  8.6,  7.3,  6.7,  8.2, 11.6, 13.8, 10.8,  6.7
 9 | 11.5, 11.4, 10.1,  7.6,  5.0,  3.7,  4.2,  6.7, 10.9, 15.8, 12.6
10 |  8.0,  8.1,  6.2,  6.6,  9.2, 10.9,  9.2,  6.6,  6.1,  9.8, 18.8


回答2:

I think the purpose of the sort is to randomly arrange the items in the list. The anonymous function to the sort() method is either going to return a positive or negative value, which is precisely what the callback is supposed to do.

The sort callback is supposed to be used to compare two items, and return either -1, 0, or -1 for less than, equality, and greater than, respectively.

Now there's probably another discussion about whether that is a good way to randomize, because the comparing function could return different values for the same two objects on discrete calls.....



回答3:

The argument to sort is a sorting callback, it is a function that supposed to take two values being sorted as arguments and return negative, 0, or positive depending if first value compared is lesser, equal, or greater than second.

In your particular example, this callback completely ignores actual values compared and instead generates a random number with Math.random, that returns a value in range 0 .. 1 and subtracts it from 0.5 to change resulting range to -0.5 .. 0.5. This makes sort randomly assume one value being lesser or greater than another and ends in generating list shuffled randomly instead of sorted by some "real" condition.