JavaScript - sorting an array of IDs based on another array of IDS that is a subset of it

自古美人都是妖i 提交于 2021-01-29 11:13:11

问题


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},

回答1:


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);



回答2:


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);


来源:https://stackoverflow.com/questions/65675712/javascript-sorting-an-array-of-ids-based-on-another-array-of-ids-that-is-a-sub

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!