1

I have two arrays:

let x = ['a', 'b', 'c']
let y = ['z', 'c', 'a']

I want to sort y based on the order defined in x . I have tried this approach:

y.sort((a,b) => { return x.indexOf(b) - x.indexOf(a) })

The problem is that it does not keep the unique order defined in x

let x = ['a', 'b', 'c']
let y = ['z', 'c', 'a']

y.sort((a,b) => { return x.indexOf(b) - x.indexOf(a) })

console.log(y);

I want to receive the output: ['a', 'c', 'z'] instead of ['c', 'a', 'z']

Andreas
  • 21,535
  • 7
  • 47
  • 56

2 Answers2

0

First of all, you are sorting descending, because you take the index of the second parameter first and vice versa.

Then you have a problem with unknow items, they get -1 and are sorted on top, but you need this items to sort to bottom.


You could take Infinity as default value to sort unknown items to the bottom.

Array#indexOf returns -1 for items wo are not in the array, + 1 gives a value which is usable with logical OR || and Infinity is a value, big enough to move the item to bottom.

var x = ['a', 'b', 'c'],
    y = ['z', 'c', 'a'];

y.sort((a, b) => (x.indexOf(a) + 1 || Infinity) - (x.indexOf(b) + 1 || Infinity));

console.log(y); // a c z
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
-1

You just need to use Array.prototype.sort and pass to it a sorting function that sorts based on the index position of the element in the other array(if it exists). See comments in sorting function for more details:

let x = ['a', 'b', 'c'];
let y = ['z', 'c', 'a'];

const sort = (positions, arr) => {
  const sorter = (a, b) => {
    const idxA = positions.indexOf(a);
    const idxB = positions.indexOf(b);

    //If a doesn't exist in positions, it should come after whatever it's being compared to
    if (idxA === -1) {
      return 1;
    }

    //If a does exist in positions, but b doesnt, b should come after
    if (idxB === -1) {
      return -1
    }

    //Compare the indexes since they both exist
    return idxA - idxB;
  }

  return arr.sort(sorter);
}

console.log(sort(x, y));
Tom O.
  • 5,730
  • 2
  • 21
  • 35