2

I have a 2D array and I'm using a custom sort function to sort it by column. My code structure is similar to this:

function sortBy(array, primaryCol, secondaryCol) {
    function compareNumber(a, b) {
        if (a[primaryCol] == b[primaryCol]) {
            return a[secondaryCol] - b[secondaryCol] ? -1 : 1;
        }
        return a[primaryCol] - b[primaryCol];
    }
    array.sort(compareNumber);
}
sortBy(colors, 3, 0);

Inside the compareNumber function, I'm accessing primaryCol and secondaryCol parameters of the sortBy function. What I want to do is move compareNumber function outside of sortBy. In that case, the code won't work, because compareNumber can't access primaryCol and secondaryCol. Also passing primaryCol and secondaryCol to compareNumber function doesn't do any good, because I guess it takes only two arguments.

function compareNumber(a, b, primaryCol, secondaryCol) {
    if (a[primaryCol] == b[primaryCol]) {
        return a[secondaryCol] < b[secondaryCol] ? -1 : 1;
    }
    return a[primaryCol] - b[primaryCol];
}
function sortBy(array, primaryCol, secondaryCol) {
    array.sort(compareNumber, primaryCol, secondaryCol);
}
sortBy(colors, 3, 0);

So, is there any way to make this work, pass additional arguments to sort function other than a and b?

2 Answers 2

1

You could use a bind to pass it parameters:

function compareNumber(a, b) {
    if (a[this[0]] == b[this[0]]) {
        return a[this[0]] < b[this[1]] ? -1 : 1;
    }
    return a[this[0]] - b[this[0]];
}
function sortBy(array, primaryCol, secondaryCol) {
    array.sort(compareNumber.bind([primaryCol, secondaryCol]));
}
sortBy(colors, 3, 0);

The bound argument now becomes assigned to the this value, so your pirmaryCol is in this[0] and your secondary is in this[1].

Sign up to request clarification or add additional context in comments.

1 Comment

This seems to be more applicable to my problem, because the number of the columns isn't going to be fixed. It'll vary. And assigning an array to this seems easier. Otherwise I'll have to pass each column manually.
1

Add the extra params then wrap or .bind the comparator to pass in these arguments with every invocation

function compareNumber(primaryCol, secondaryCol, a, b) {
    if (a[primaryCol] == b[primaryCol]) {
        return a[secondaryCol] - b[secondaryCol] ? -1 : 1;
    }
    return a[primaryCol] - b[primaryCol];
}

function sortBy(array, primaryCol, secondaryCol) {
    array.sort(compareNumber.bind(null, primaryCol, secondaryCol));
}
sortBy(colors, 3, 0);

Or

// ...
    array.sort(function (a, b) {return compareNumber(primaryCol, secondaryCol, a, b);});
// ...

If your comparator uses this then I'd recommend .bind as there is less overhead in the one-off than needing to .call or .apply each time.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.