5

I have several arrays like:

var arr1 = ['A', 'B', 'C', 'D'], 
    arr2 = ['A', 'C', 'D'],
    arr3 = ['B', 'D'];

I now want them being sorted by a custom pattern, e.g. ['D', 'C', 'A', 'B']. I am using lodash and looking for a smart way of doing this.

1
  • You want each array sorted by the same pattern? Commented Oct 13, 2015 at 11:58

3 Answers 3

13

You can use an object to efficiently map values to sortable values:

var arr1 = [ "A", "B", "C", "D" ];

var map = { D: 1, C: 2, A: 3, B: 4 };
arr1.sort(function(x, y){ return map[x] - map[y]; });

// show result in snippet
document.write(JSON.stringify(arr1));

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

Comments

2

The same basic idea as Guffa's solution, but with a reusable API:

var makeSorter = function(pattern) {
    var map = _.mapValues(_.invert(pattern), Number);
    return function(vals) {
        return vals.sort(function(a, b) {
            return map[a] - map[b];
        });
    };
};


var mySorter = makeSorter(['D', 'C', 'A', 'B']);
mySorter(['A', 'B', 'C', 'D']); //=> ["D", "C", "A", "B"]
mySorter(['A', 'C', 'D']); //=> ["D", "C", "A"]

If there might be values in your data not in your pattern, then you might need something slightly more complex:

var makeSorter = function(pattern) {
    var map = _.mapValues(_.invert(pattern), function(s) {return Number(s) + 1;});
    return function(vals) {
        return vals.sort(function(a, b) {
            return (map[a] || Infinity) - (map[b] || Infinity);
        });
    };
};

mySorter(['A', 'X', 'B', 'C', 'Q']); //=> ["C", "A", "B", "X", "Q"]

Also, how nice ES6 arrow functions are. This is the equivalent of the first version, in ES6:

var makeSorter = pattern => {
    let map = _.mapValues(_.invert(pattern), Number);
    return vals => vals.sort((a, b) => map[a] - map[b]);
};

Comments

0
var pattern = ['D', 'C', 'A', 'B'];

function sortArray (array, pattern) {
    return array.sort(function (a, b) {
        if (pattern.indexOf(a) === pattern.indexOf(b)) {
            return 0;
        } else {
            return pattern.indexOf(a) > pattern.indexOf(b) ? 1 : -1;
        }
    });
}

// use like:
var sortedArray = sortArray(['A', 'C', 'D'], pattern);

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.