Skip to content

Instantly share code, notes, and snippets.

@aquaductape
Created June 19, 2019 21:46
Show Gist options
  • Save aquaductape/a3d7c16b1d745bf993f68822925ef75d to your computer and use it in GitHub Desktop.
Save aquaductape/a3d7c16b1d745bf993f68822925ef75d to your computer and use it in GitHub Desktop.
// Array prototype method, however this is not safe, since it is added to the global scope
// definedProperty makes method non-enumerable as well as adding new property to in this case, to Array prototype
// Array prototype method, however this is not safe, since it is added to the global scope
// definedProperty makes method non-enumerable as well as adding new property to in this case, to Array prototype
Object.defineProperty(Array.prototype, 'mySort', {
// webkit and chrome uses quicksort
// mozilla uses merge sort
// For my sort algorithm, it uses merge sort
// But I also chose chrome's interpretation of callback return boolean value, just because I mainly use chrome
value: function(callback) {
// if there is no callback
const defaultMerge = (left, right) => {
const results = [];
while (left.length && right.length) {
// toString method fails on null, using type coersion instead
if (left[0] + '' > right[0] + '') {
results.push(right.shift());
} else {
results.push(left.shift());
}
}
return [...results, ...left, ...right];
};
// if callback is provided
const callbackMerge = (left, right) => {
const results = [];
while (left.length && right.length) {
const result = callback(left[0], right[0]);
// to my understanding it seems to me that in chrome,
// it ignores boolean value from callback and strictly wants numerical sign values
// mozilla does accept boolean values
// in this case I'm choosing chrome's interpretation
if (typeof result === 'boolean') {
break;
}
if (Math.sign(result) === -1) {
results.push(left.shift());
} else {
results.push(right.shift());
}
}
return [...results, ...left, ...right];
};
const mergeSort = arr => {
if (arr.length === 1) {
return arr;
}
const mid = Math.floor(arr.length / 2);
const left = arr.slice(0, mid);
const right = arr.slice(mid);
return merge(mergeSort(left), mergeSort(right));
};
let merge = callbackMerge;
if (callback === undefined) {
merge = defaultMerge;
}
const length = this.length;
const cleanArr = [];
// removes empty slots
const undefinedValues = this.filter(el => {
if (el !== undefined) {
cleanArr.push(el);
}
return el === undefined;
});
const sortedArr = mergeSort(cleanArr);
sortedArr.push(...undefinedValues);
const sortedArrLength = sortedArr.length;
// replaces array items with sorted array items
for (let i = 0; i < sortedArrLength; i++) {
this[i] = sortedArr[i];
}
// sortedArr will be shorter if original array contains empty slots
// last remaining items will be duplicates
if (sortedArrLength < length) {
// deletes duplicates at end of array, by shortening the length
this.length = sortedArrLength;
// restores empty items at end of array, by extending the length
this.length = length;
}
return this;
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment