forto-sorter
Version:
Fast and powerful array sorting. Sort by any property in any direction with easy to read syntax.
55 lines (47 loc) • 1.53 kB
text/typescript
export const mergeSort = ({ list }, { shouldSwap }) => {
/**
* @return {number}
*/
const getMiddleIndex = (startIndex, endIndex) => (
startIndex + Math.floor((endIndex - startIndex) / 2)
);
/**
* merges two sorted partitions using a temporary array
* @return {array} the start and end of a partition
*/
const partitionAndSort = (startIndex = 0, endIndex = list.length - 1) => {
if (endIndex - startIndex <= 0) return [startIndex, startIndex + 1];
const middleIndex = getMiddleIndex(startIndex, endIndex);
const leftPartition = partitionAndSort(startIndex, middleIndex);
const rightPartition = partitionAndSort(middleIndex + 1, endIndex);
const [leftStart, leftEnd] = leftPartition;
const [rightStart, rightEnd] = rightPartition;
const merged = [];
let leftIndex = leftStart;
let rightIndex = rightStart;
while (leftIndex < leftEnd || rightIndex < rightEnd) {
if (rightIndex === rightEnd) {
merged.push(list[leftIndex]);
leftIndex += 1;
} else if (leftIndex === leftEnd) {
merged.push(list[rightIndex]);
rightIndex += 1;
} else if (shouldSwap(leftIndex, rightIndex)) {
merged.push(list[rightIndex]);
rightIndex += 1;
} else {
merged.push(list[leftIndex]);
leftIndex += 1;
}
}
// update list segment with merged partition
let j = 0;
for (let i = leftStart; i < rightEnd; i += 1) {
list[i] = merged[j]; // eslint-disable-line no-param-reassign
j += 1;
}
return [leftStart, rightEnd];
};
partitionAndSort();
return list;
};