0

I have an array of objects that also contain IDs like so:

const arr = [
   { id: "5ffca1c771138d181c3bde0b", otherValue: 10 }, 
   { id: "5ffca1c771138d181c3bde0e", otherValue: 3}, 
   { id: "5ffca1c771138d181c3bde12", otherValue: 7},
   { id: "5ffca1c771138d181c3bde04" otherValue: 1}, 
   { id: "5ffca1c771138d181c3bde08", otherValue: 11}
]

I then have second array, that contains a subset of the IDs of the first array in a particular ordering, like so:

const arrIds = [ "5ffca1c771138d181c3bde12", "5ffca1c771138d181c3bde08"];

I now want to sort the first array, so that the ordering is the same as in the second array, meaning the ordered subset is first, and the rest follows after, so that I get something like this:

[
   { id: "5ffca1c771138d181c3bde12", otherValue: 7}, // 1st place in subset
   { id: "5ffca1c771138d181c3bde08", otherValue: 11} // 2nd place in subset
   { id: "5ffca1c771138d181c3bde0b", otherValue: 10 }, // rest
   { id: "5ffca1c771138d181c3bde0e", otherValue: 3, // rest
   { id: "5ffca1c771138d181c3bde04" otherValue: 1}, // rest
]

How does the sorting function for this look like?

Current implementation:

arr.slice().sort((a, b) => arrIds.indexOf(a) - arrIds.indexOf(b))

which results in:

   { id: "5ffca1c771138d181c3bde0b", otherValue: 10 }, 
   { id: "5ffca1c771138d181c3bde0e", otherValue: 3, 
   { id: "5ffca1c771138d181c3bde04" otherValue: 1}, 
   { id: "5ffca1c771138d181c3bde12", otherValue: 7},
   { id: "5ffca1c771138d181c3bde08", otherValue: 11},
3
  • Does this answer your question? How do I sort an array of objects based on the ordering of another array? Commented Jan 11, 2021 at 22:58
  • no, since it's not a subset Commented Jan 11, 2021 at 22:59
  • Edit your question to show how you tried to implement it and how it didn't work. Also note there are 8 answers to the question; not all of them depend on it being a subset. Commented Jan 11, 2021 at 23:02

2 Answers 2

2

Below is a simple example, I've used IndexOf to get the index and sort on this for the first part,. Only slight gotcha is that -1 would be at the wrong side of the sort, so a check for this and I just return a large number to place at the end instead.

The second stage of the sort is then performed on an equality check, and it's just a simple (b-a) compare, for a descending sort.

const arr = [
   { id: "5ffca1c771138d181c3bde0b", otherValue: 10 }, 
   { id: "5ffca1c771138d181c3bde0e", otherValue: 3}, 
   { id: "5ffca1c771138d181c3bde12", otherValue: 7},
   { id: "5ffca1c771138d181c3bde04", otherValue: 1}, 
   { id: "5ffca1c771138d181c3bde08", otherValue: 11}
];

const arrIds = [ "5ffca1c771138d181c3bde12", "5ffca1c771138d181c3bde08"];

function s1(a) {
  let i = arrIds.indexOf(a.id);
  if (i < 0) i = Number.MAX_SAFE_INTEGER;
  return i;
}

arr.sort((a,b) => {
  let s = s1(a) - s1(b);
  if (s === 0) return b.otherValue - a.otherValue;
  return s;
});

console.log(arr);

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

3 Comments

Plus one, but I would change if(i < 0) i = 100000; to if(i < 0)i = Infinity; even though the Browser would probably crash with such a large Array.
@StackSlave Yeah, I was trying to remember what the constant was for a large integer, Number.MAX_SAFE_INTEGER so updated now , I'm not sure but I think Infinity might cause issues as it's maths are not logical.. eg. Infinity - Infinity = NaN etc, so could mess up the sort at s1(a) - s1(b)
Oops... yeah, I would do Number.MAX_SAFE_INTEGER instead.
0

You could use Map Object because it would make your index searching faster when sorting.

const arr = [
  { id: '5ffca1c771138d181c3bde0b', otherValue: 10 },
  { id: '5ffca1c771138d181c3bde0e', otherValue: 3 },
  { id: '5ffca1c771138d181c3bde12', otherValue: 7 },
  { id: '5ffca1c771138d181c3bde04', otherValue: 1 },
  { id: '5ffca1c771138d181c3bde08', otherValue: 11 },
];
const arrIds = ['5ffca1c771138d181c3bde12', '5ffca1c771138d181c3bde08'];
const map = new Map();
arrIds.forEach((x, i) => map.set(x, i));
arr.sort(
  (x, y) =>
    (map.get(x.id) ?? Number.MAX_VALUE) - (map.get(y.id) ?? Number.MAX_VALUE)
);
console.log(arr);

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.