2

I'm attempting to build out a monkey-patched version of mergeSort but I'm running into errors every single time. I've ran through debugger a few times and it looks like everything is sorting properly until the last step where I jump to a line in a loader.js file.

Can anyone help me check this out? Thanks in advance!


Array.prototype.mergeSort = function(callback) {
    if (this.length <= 1) return this;

    if (!callback) {
        callback = function(x, y) {
            if (x > y) return -1;
            else if (x < y) return 1;
            else return 0;
        };
    }

    const mid = Math.floor(this.length / 2);
    const sortedLeft = this.slice(0, mid).mergeSort(callback);
    const sortedRight = this.slice(mid).mergeSort(callback);

    return sortedLeft.merge(sortedRight, callback);
};

Array.prototype.merge = function(arr, callback) {
    let merged = [];

    while (this.length > 0 || arr.length > 0) {
        if (callback(this[0], arr[0]) < 0) {
            merged.push(arr.shift());
            break;
        } else if (callback(this[0], arr[0]) >= 0) {
            merged.push(this.shift());
            break;
        }
    }

    merged = merged.concat(this);
    merged = merged.concat(arr);

    return merged;
};

7
  • Side note; your first callback = ... part is effectively the same as return y - x; Commented Apr 16, 2019 at 22:20
  • Second side note; } else if (callback(this[0], arr[0]) >= 0) { is just an else statement when paired with the first if. Commented Apr 16, 2019 at 22:24
  • Understood on both counts, cleaned it up a bit but still having issues for some reason. Commented Apr 16, 2019 at 22:40
  • @Taplar: not really, for example return y - x does not handle strings whereas the OP's default comparison function does. Commented Apr 18, 2019 at 6:58
  • @chqrlie if the values are string, subtraction isn't appropriate in the first place, and should be using the native localeCompare instead. Commented Apr 18, 2019 at 14:28

1 Answer 1

2

The merge loop should stop when either list is empty: instead of while (this.length > 0 || arr.length > 0) you should write:

while (this.length > 0 && arr.length > 0)

Furthermore you should not break from the loop after each store into the merge array, and it is redundant to compare the elements twice.

Here is a corrected version:

Array.prototype.merge = function(arr, callback) {
    let merged = [];

    while (this.length > 0 && arr.length > 0) {
        if (callback(this[0], arr[0]) < 0) {
            merged.push(arr.shift());
        } else {
            merged.push(this.shift());
        }
    }
    merged = merged.concat(this);
    return merged.concat(arr);
};

Note however that your merge method sorts the array in descending order and the default callback function compares the elements in descending order too, causing the array to be sorted in increasing order by coincidence. You might want to simplify this and accept a null callback function in merge.

Here is a more generic version:

Array.prototype.mergeSort = function(callback) {
    if (this.length <= 1)
        return this;

    const mid = this.length >> 1;
    const sortedLeft = this.slice(0, mid).mergeSort(callback);
    const sortedRight = this.slice(mid).mergeSort(callback);

    return sortedLeft.merge(sortedRight, callback);
};

Array.prototype.merge = function(arr, callback) {
    let merged = [];

    if (callback) {
        while (this.length > 0 && arr.length > 0) {
            if (callback(this[0], arr[0]) <= 0) {
                merged.push(this.shift());
            } else {
                merged.push(arr.shift());
            }
        }
    } else {
        while (this.length > 0 && arr.length > 0) {
            if (this[0] <= arr[0]) {
                merged.push(this.shift());
            } else {
                merged.push(arr.shift());
            }
        }
    }
    return merged.concat(this).concat(arr);
};
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.