Skip to content

Commit 27fd496

Browse files
committed
Updated to stablesort 0.1.8 and recoded to fit our style. Removed inplace static function.
1 parent 0d934c7 commit 27fd496

1 file changed

Lines changed: 106 additions & 79 deletions

File tree

src/utils/array/StableSort.js

Lines changed: 106 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,170 @@
11
/**
22
* @author Richard Davey <rich@photonstorm.com>
3+
* @author Angry Bytes (and contributors)
34
* @copyright 2020 Photon Storm Ltd.
45
* @license {@link https://opensource.org/licenses/MIT|MIT License}
56
*/
67

7-
//! stable.js 0.1.6, https://github.com/Two-Screen/stable
8-
//! © 2017 Angry Bytes and contributors. MIT licensed.
9-
108
/**
11-
* @namespace Phaser.Utils.Array.StableSortFunctions
12-
*/
13-
14-
(function() {
15-
16-
/**
17-
* A stable array sort, because `Array#sort()` is not guaranteed stable.
18-
* This is an implementation of merge sort, without recursion.
9+
* The comparator function.
1910
*
20-
* @function Phaser.Utils.Array.StableSort
21-
* @since 3.0.0
11+
* @ignore
2212
*
23-
* @param {array} arr - The input array to be sorted.
24-
* @param {function} comp - The comparison handler.
13+
* @param {*} a - The first item to test.
14+
* @param {*} b - The second itemt to test.
2515
*
26-
* @return {array} The sorted result.
16+
* @return {boolean} True if they localCompare, otherwise false.
2717
*/
28-
var stable = function(arr, comp) {
29-
return exec(arr.slice(), comp);
30-
};
18+
function Compare (a, b)
19+
{
20+
return String(a).localeCompare(b);
21+
}
3122

32-
/**
33-
* Sort the input array and simply copy it back if the result isn't in the original array, which happens on an odd number of passes.
23+
/**
24+
* Process the array contents.
3425
*
35-
* @function Phaser.Utils.Array.StableSortFunctions.inplace
36-
* @memberof Phaser.Utils.Array.StableSortFunctions
37-
* @since 3.0.0
3826
* @ignore
3927
*
40-
* @param {array} arr - The input array.
41-
* @param {function} comp - The comparison handler.
28+
* @param {array} array - The array to process.
29+
* @param {function} compare - The comparison function.
4230
*
43-
* @return {array} The sorted array.
31+
* @return {array} - The processed array.
4432
*/
45-
stable.inplace = function(arr, comp) {
46-
var result = exec(arr, comp);
47-
48-
// This simply copies back if the result isn't in the original array,
49-
// which happens on an odd number of passes.
50-
if (result !== arr) {
51-
pass(result, null, arr.length, arr);
52-
}
53-
54-
return arr;
55-
};
56-
57-
// Execute the sort using the input array and a second buffer as work space.
58-
// Returns one of those two, containing the final result.
59-
function exec(arr, comp) {
60-
if (typeof(comp) !== 'function') {
61-
comp = function(a, b) {
62-
return String(a).localeCompare(b);
63-
};
64-
}
65-
33+
function Process (array, compare)
34+
{
6635
// Short-circuit when there's nothing to sort.
67-
var len = arr.length;
68-
if (len <= 1) {
69-
return arr;
36+
var len = array.length;
37+
38+
if (len <= 1)
39+
{
40+
return array;
7041
}
7142

7243
// Rather than dividing input, simply iterate chunks of 1, 2, 4, 8, etc.
7344
// Chunks are the size of the left or right hand in merge sort.
7445
// Stop when the left-hand covers all of the array.
7546
var buffer = new Array(len);
76-
for (var chk = 1; chk < len; chk *= 2) {
77-
pass(arr, comp, chk, buffer);
7847

79-
var tmp = arr;
80-
arr = buffer;
48+
for (var chk = 1; chk < len; chk *= 2)
49+
{
50+
RunPass(array, compare, chk, buffer);
51+
52+
var tmp = array;
53+
54+
array = buffer;
55+
8156
buffer = tmp;
8257
}
8358

84-
return arr;
59+
return array;
8560
}
8661

87-
// Run a single pass with the given chunk size.
88-
var pass = function(arr, comp, chk, result) {
62+
/**
63+
* Run a single pass with the given chunk size.
64+
*
65+
* @ignore
66+
*
67+
* @param {array} arr - The array to run the pass on.
68+
* @param {function} comp - The comparison function.
69+
* @param {number} chk - The number of iterations.
70+
* @param {array} result - The array to store the result in.
71+
*/
72+
function RunPass (arr, comp, chk, result)
73+
{
8974
var len = arr.length;
9075
var i = 0;
76+
9177
// Step size / double chunk size.
9278
var dbl = chk * 2;
79+
9380
// Bounds of the left and right chunks.
9481
var l, r, e;
82+
9583
// Iterators over the left and right chunk.
9684
var li, ri;
9785

9886
// Iterate over pairs of chunks.
99-
for (l = 0; l < len; l += dbl) {
87+
for (l = 0; l < len; l += dbl)
88+
{
10089
r = l + chk;
10190
e = r + chk;
102-
if (r > len) r = len;
103-
if (e > len) e = len;
91+
92+
if (r > len)
93+
{
94+
r = len;
95+
}
96+
97+
if (e > len)
98+
{
99+
e = len;
100+
}
104101

105102
// Iterate both chunks in parallel.
106103
li = l;
107104
ri = r;
108-
while (true) {
105+
106+
while (true)
107+
{
109108
// Compare the chunks.
110-
if (li < r && ri < e) {
109+
if (li < r && ri < e)
110+
{
111111
// This works for a regular `sort()` compatible comparator,
112112
// but also for a simple comparator like: `a > b`
113-
if (comp(arr[li], arr[ri]) <= 0) {
113+
if (comp(arr[li], arr[ri]) <= 0)
114+
{
114115
result[i++] = arr[li++];
115116
}
116-
else {
117+
else
118+
{
117119
result[i++] = arr[ri++];
118120
}
119121
}
120-
// Nothing to compare, just flush what's left.
121-
else if (li < r) {
122+
else if (li < r)
123+
{
124+
// Nothing to compare, just flush what's left.
122125
result[i++] = arr[li++];
123126
}
124-
else if (ri < e) {
127+
else if (ri < e)
128+
{
125129
result[i++] = arr[ri++];
126130
}
127-
// Both iterators are at the chunk ends.
128-
else {
131+
else
132+
{
133+
// Both iterators are at the chunk ends.
129134
break;
130135
}
131136
}
132137
}
133-
};
134-
135-
// Export using CommonJS or to the window.
136-
if (typeof(module) !== 'undefined') {
137-
module.exports = stable;
138-
}
139-
else {
140-
window.stable = stable;
141138
}
142139

143-
})();
140+
/**
141+
* An in-place stable array sort, because `Array#sort()` is not guaranteed stable.
142+
*
143+
* This is an implementation of merge sort, without recursion.
144+
*
145+
* Function based on the Two-Screen/stable sort 0.1.8 from https://github.com/Two-Screen/stable
146+
*
147+
* @function Phaser.Utils.Array.StableSort
148+
* @since 3.0.0
149+
*
150+
* @param {array} array - The input array to be sorted.
151+
* @param {function} [compare] - The comparison function.
152+
*
153+
* @return {array} The sorted result.
154+
*/
155+
var StableSort = function (array, compare)
156+
{
157+
if (compare === undefined) { compare = Compare; }
158+
159+
var result = Process(array, compare);
160+
161+
// This simply copies back if the result isn't in the original array, which happens on an odd number of passes.
162+
if (result !== array)
163+
{
164+
RunPass(result, null, array.length, array);
165+
}
166+
167+
return array;
168+
};
169+
170+
module.exports = StableSort;

0 commit comments

Comments
 (0)