How to make an array() follow a rule on sorting elements

Viewed 441

The array can have different size but max it could contain the following elements:

DE/FR/IT/EN/RM

some of the possible arrays could be:

DE/FR/IT/EN/RM,

IT/EN/RM,

DE/RM

etc.

How can I make an array like that follow a sorting rule? By meaning how can I make that array always sort itself following this order: DE/FR/IT/EN/RM

I tried something like this, but as not being a js coder I cant make any sense out of it:

function{
.....
....
...
list.sort(compareList());
...
..
.
}

function compareList() {
    var ruleList = new Array();
    ruleList.push("DE","FR","IT","EN","RM");


}

E.g.

input array with 3 elements: RM,DE,EN

to output after sorting: DE,EN,RM

OR e.g

input with the maxed 5 elements: FR,DE,EN,RM,IT

to output:DE,FR,IT,EN,RM

3 Answers

You could take an object for the wanted order and a default value for not known value and sort by the delta of the values. Not known items are sorted to the end of the array.

function compareList() {
    var order = { DE: 1, FR: 2, IT: 3, EN: 4, RM: 5, default: Infinity };
    return (a, b) => (order[a] || order.default) - (order[b] || order.default);
}

console.log(['RM', 'DE', 'EN'].sort(compareList()));             // DE EN RM
console.log(['FR', 'DE', 'EN', 'RM', 'IT'].sort(compareList())); // DE FR IT EN RM
.as-console-wrapper { max-height: 100% !important; top: 0; }

For keeping the first element, you could give that value a great negative value for sorting. This works only by knowing the array in advance, because on later sorting, there is no information about an index.

const
    keepFirst = (array, sort) => {
        var order = array.reduce((r, v, i) => (r[v] = i + 1, r), { default: Infinity });
        order[array[0]] = -Infinity;
        return array.sort((a, b) => (order[a] || order.default) - (order[b] || order.default));
    },
    order = ['DE', 'FR', 'IT', 'EN', 'RM'];

console.log(keepFirst(['RM', 'DE', 'EN'], order).join(' '));             // RM DE EN
console.log(keepFirst(['FR', 'DE', 'EN', 'RM', 'IT'], order).join(' ')); // FR DE IT EN RM

var base =  ["DE","FR","IT","EN","RM"];
var test = ["DE","IT","FR","EN"];
test.sort((a,b) => base.indexOf(a) - base.indexOf(b));
console.log(test);

You can use the index of the base array as the order

var base =  ["DE","FR","IT","EN","RM"];
var test = ["DE","IT","FR","EN"];
test.sort((a,b) => base.indexOf(a) - base.indexOf(b));
console.log(test);

You could define a function like sortArrayBy() below to achieve this:

// The sorting function, sorts input array by the by array
function sortArrayBy(input, by) {

  var result = [].concat(input)

  result.sort(( str0, str1 ) => {

     const idx0 = by.indexOf(str0)
     const idx1 = by.indexOf(str1)

     // If str0 or str1 not found in by array, push these
     // to bottom of result
     if(idx0 === -1) return 1
     if(idx1 === -1) return -1

     return idx0 - idx1
  })
  
  return result;
}

var data = ['DE','FR','IT','EN','RM']

console.log('DE/FR/IT/EN/RM', sortArrayBy(data, ['DE','FR','IT','EN','RM']))
console.log('IT/EN/RM', sortArrayBy(data, ['IT','EN','RM']))
console.log('DE/RM', sortArrayBy(data, ['DE','RM']))

This sortArrayBy() method effectively takes an index array (ie by) that is used to direct the sorting/ordering of input data (ie ['DE','FR','IT','EN','RM']) in the returned result array,

Related