-1

I've two array of objects one selected and other general data which we're displaying

General data for display

const arr = [
  {
    id: "1",
    name: "Skoda - Auto"
  },
  {
    id: "2",
    name: "BMW - Auto"
  },
  {
    id: "3",
    name: "Mustang"
  },
  {
    id: "2",
    name: "Ferrari"
  },
  {
    id: "1",
    name: "Ford"
  }
];
selectedValues 

const selectedArr = [
  {
    id: "1",
    name: "something - 1"
  },
 {
    id: "3",
    name: "something - 1"
  }
]

I want to sort the general data for display based on this selected array. so basically I want to match the id from selectedArr check if this id is present in general array if yes the shuffle the general array so that selected values are at the top of the array O/P

const arr = [
  {
    id: "1",
    name: "Skoda - Auto"
  },
  {
    id: "1",
    name: "Ford"
  },
  {
    id: "3",
    name: "Mustang"
  },
  {
    id: "2",
    name: "BMW - Auto"
  },
  {
    id: "2",
    name: "Ferrari"
  },
];

There are multiple values with same id, I need to unshift those values at the top if it exisits in selected Array. I'm not sure how to achieve such output, hence need some help on this

Kriti
  • 9
  • 3
  • Does this answer your question? [Javascript - sort array based on another array](https://stackoverflow.com/questions/13304543/javascript-sort-array-based-on-another-array) – pilchard Aug 18 '23 at 10:47
  • also [Sort array of objects by array of IDs](https://stackoverflow.com/questions/41097756/sort-array-of-objects-by-array-of-ids) or [Sort an array of objects based on another array of ids](https://stackoverflow.com/questions/35538509/sort-an-array-of-objects-based-on-another-array-of-ids) or [How to sort an array of objects in the same order as an id array](https://stackoverflow.com/questions/61186467/how-to-sort-an-array-of-objects-in-the-same-order-as-an-id-array) – pilchard Aug 18 '23 at 10:48

2 Answers2

0

One not very efficient but easy way to do it is to filter the array twice, creating one array that has the selected elements and one that does not, and then concatenate these two together, like the example below.

const selected = [4, 8, 3];
const fullArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const sorted = fullArray.filter((e) => selected.includes(e))
.concat(fullArray.filter((e) => !selected.includes(e)));

console.log(sorted);
Jim Nilsson
  • 838
  • 4
  • 12
  • Why not a simple [sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) instead of two filters? – Reyno Aug 18 '23 at 10:39
  • 1
    That would also be simple but also less efficient O(n logn) compared to O(n) (assuming the number of elements in `selected` is negligably small. – Jim Nilsson Aug 18 '23 at 10:41
0

This can be achieved by indexing your sorting array into a map that gives an index for a given id:

const selectedArr = [
    {
        id: "1",
        name: "something - 1"
    },
    {
        id: "3",
        name: "something - 1"
    }
]

const sortMap = new Map(selectedArr.map(({ id }, idx) => [id, idx]));

then using this in the standard sort function (here, I'm taking a copy of the array with [...arr] because sort is in-place and I'm a big fan of avoiding mutation). We give items that are not present in the sortMap a sufficiently large index that they'll go to the bottom of the list...

const sortedArray = [...arr].sort(
    (a, b) => (sortMap.get(a.id) ?? 10000000) - (sortMap.get(b.id) ?? 10000000)
);

Playground Link

const arr = [{
    id: "1",
    name: "Skoda - Auto"
  },
  {
    id: "2",
    name: "BMW - Auto"
  },
  {
    id: "3",
    name: "Mustang"
  },
  {
    id: "2",
    name: "Ferrari"
  },
  {
    id: "1",
    name: "Ford"
  }
];

const selectedArr = [{
    id: "1",
    name: "something - 1"
  },
  {
    id: "3",
    name: "something - 1"
  }
]

const sortMap = new Map(selectedArr.map(({
  id
}, idx) => [id, idx]));

const sortedArray = [...arr].sort((a, b) => (sortMap.get(a.id) ?? 10000000) - (sortMap.get(b.id) ?? 10000000));

console.log(sortedArray)
spender
  • 117,338
  • 33
  • 229
  • 351
  • can you plz explain you code, I didn't get it what's that `10000000` value? – Kriti Aug 18 '23 at 10:50
  • @Kriti OK. When we search `sortMap` for a value, what is returned is the position in the sorted list that we want the item to appear. However, some values are not present in the `sortMap` (for instance, `sortMap.get("2")` returns `undefined`), so in this case we use the null-coalescing operator `??` to substitue the value `10000000` when `undefined` is encountered. This ensures that items in the source array that are not in the `sortMap` get sorted to position `10000000` (or the end of the list). To be super-safe, you might choose `Number.MAX_VALUE` instead. – spender Aug 18 '23 at 10:55
  • The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type. - I get this error in vscode – Kriti Aug 18 '23 at 10:57
  • @Kriti Where does that error come from? As can be seen in the [typescript playground](https://tsplay.dev/mxy8xW), the data you supplied and the code I supplied don't exhibit this error. – spender Aug 18 '23 at 10:59
  • fixed it `const sortedArray = [...arr].sort( (a, b) => +(sortMap.get(a.id) ?? 10000000) - +(sortMap.get(b.id) ?? 10000000) );` https://github.com/microsoft/TypeScript/issues/5710 – Kriti Aug 18 '23 at 11:06