4

How can I sort the allGames array sorted to have the installedGames first?

const allGames = [
    { id: 2, name: 'game2' },
    { id: 1, name: 'game1' },
    { id: 4, name: 'game4' },
    { id: 3, name: 'game3' },
]
const installedGames = [
    { id: 2, name: 'game2' },
    { id: 3, name: 'game3' }
]

const sorted = allGames.sort((a, b) => {
    return a.id - b.id // but this just sorts by id
});

Basically I want to get this order:

{ id: 2, name: 'game2' },
{ id: 3, name: 'game3' },
{ id: 1, name: 'game1' },
{ id: 4, name: 'game4' }
2
  • Are these objects referencing the same object or do they only have the same id? Commented Apr 24, 2019 at 11:19
  • 1
    The objects are slightly different and i would prefer not to join the arrays if possible. Commented Apr 24, 2019 at 11:21

7 Answers 7

6

let allGames = [
    { id: 2, name: 'game2' },
    { id: 1, name: 'game1' },
    { id: 4, name: 'game4' },
    { id: 3, name: 'game3' },
]
let installedGames = [
    { id: 3, name: 'game3' },
    { id: 2, name: 'game2' },
    
]

// Step 1. sort both arrays

allGames = allGames.sort( (a,b) => a.id - b.id )
installedGames = installedGames.sort( (a,b) => a.id - b.id )

// Step 2. remove installedGames from allGames

const remainingGames = allGames.filter( game => !installedGames.find(g => g.name === game.name) )

// step 3. concatenate both

const sortedGames = installedGames.concat(remainingGames)

console.log(sortedGames)

Also, I'd suggest a model change. Instead of having two distinct arrays, I suggest having only one, and add an installed attribute to your games. This will make your life easier :

const allGames = [
    { id: 2, name: 'game2', installed : true },
    { id: 1, name: 'game1', installed : false },
    { id: 4, name: 'game4', installed : false },
    { id: 3, name: 'game3', installed : true },
]

const sortedGames = allGames.sort((a, b) =>
     +b.installed - +a.installed || a.id - b.id
);

console.log(sortedGames)

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

Comments

6

You can use sort method and inside findIndex and then check if index is -1 and sort by results.

const allGames = [{ id: 2, name: 'game2' },{ id: 1, name: 'game1' },{ id: 4, name: 'game4' },{ id: 3, name: 'game3' },]
const installedGames = [{ id: 2, name: 'game2' },{ id: 3, name: 'game3' }]

allGames.sort((a, b) => {
  const ai = installedGames.findIndex(({id}) => id === a.id);
  const bi = installedGames.findIndex(({id}) => id === b.id)
  return (bi != -1) - (ai != -1) || ai - bi
});

console.log(allGames)

You could also create object form installed games and sort by that object.

const allGames = [{ id: 2, name: 'game2' },{ id: 1, name: 'game1' },{ id: 4, name: 'game4' },{ id: 3, name: 'game3' },]
const installedGames = [{ id: 2, name: 'game2' },{ id: 3, name: 'game3' }]
const inst = installedGames.reduce((r, {id}, i) => Object.assign(r, {[id]: i}), {})

allGames.sort((a, b) => (b.id in inst) - (a.id in inst) || inst[a.id] - inst[b.id]);
console.log(allGames)

Comments

3

Here is my try:

const allGames = [
    { id: 2, name: 'game2' },
    { id: 1, name: 'game1' },
    { id: 4, name: 'game4' },
    { id: 3, name: 'game3' },
]
const installedGames = [
    { id: 2, name: 'game2' },
    { id: 3, name: 'game3' }
];

var ids = installedGames.map(x => x.id);

const sorted = allGames.slice().sort((a, b) => {
    var pos_a = ids.indexOf(a.id);
    var pos_b = ids.indexOf(b.id);
    // compare both installed
    if (pos_a !== -1 && pos_b !== -1) {
      return pos_a - pos_b;
    }
    // compare installed and not installed
    if (pos_a != -1) {
      return -1;
    }
    // sort the rest
    return 1;
});
console.log(sorted);

Comments

3

I think this is the fastest way to solve this problem.

 const allGames = [
    { id: 2, name: 'game2' },
    { id: 1, name: 'game1' },
    { id: 4, name: 'game4' },
    { id: 3, name: 'game3' },
]
const installedGames = [
    { id: 2, name: 'game2' },
    { id: 3, name: 'game3' }
]

const output = [
    ...installedGames,
    ...allGames.filter( io => installedGames.findIndex(il => io.id === il.id) === -1 )
];

Comments

2

The criteria for comparing a and b is as follows:

  • If both items are installed or both items are not installed then item with smaller id first
  • Else (it is guaranteed that one is installed and other is not so) installed item first

const allGames = [
    { id: 2, name: 'game2' },
    { id: 1, name: 'game1' },
    { id: 4, name: 'game4' },
    { id: 3, name: 'game3' },
]
const installedGames = [
    { id: 2, name: 'game2' },
    { id: 3, name: 'game3' }
];
allGames.sort(function(a, b) {
    // findIndex returns quicker than filter
    var ai = installedGames.findIndex(game => game.id === a.id) >= 0;
    var bi = installedGames.findIndex(game => game.id === b.id) >= 0;

    // ai === bi   -> both items are installed or both items are not installed
    // a.id - b.id -> item with smaller id first
    // ai - bi     -> if 1 - 0 then return -1, if 0 - 1 then return +1
    return ai === bi ? (a.id - b.id) : -(ai - bi);
});
console.log(allGames);

Comments

2

You can try following.

Firstly to improve the performance, create a map with key as id and value as its index in installedGames array. Then sort the first array based on the indexes stored in map.

Map second array and create an array of ids. Now sort first array based on the

const allGames = [{ id: 2, name: 'game2' },{ id: 1, name: 'game1' },{ id: 4, name: 'game4' },{ id: 3, name: 'game3' }];
const installedGames = [{ id: 2, name: 'game2' },{ id: 3, name: 'game3' }];

const obj = installedGames.reduce((a,c,i) => Object.assign(a, {[c.id]:i}), {});

allGames.sort((a,b) => {
  let aIndex = obj[a.id], bIndex = obj[b.id];
  return aIndex != undefined ? bIndex != undefined ? aIndex - bIndex : -1 : 1;
});
console.log(allGames);

Comments

0

you can try this

const allGames = [
    { id: 2, name: 'game2' },
    { id: 1, name: 'game1' },
    { id: 4, name: 'game4' },
    { id: 3, name: 'game3' },
]
const installedGames = [
    { id: 2, name: 'game2' },
    { id: 3, name: 'game3' }
]

const sorted = ((a, b) => {
    return a.id - b.id //this just sorts by id
});
var out  = [...installedGames.sort(sorted), ...allGames.filter(o=> !(installedGames.map(i => i.id).indexOf(o.id) > -1)).sort(sorted)]

console.log(out)

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.