Reputation: 9915
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' }
Upvotes: 4
Views: 148
Reputation: 28475
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);
Upvotes: 2
Reputation: 272236
The criteria for comparing a
and b
is as follows:
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);
Upvotes: 2
Reputation: 176
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 )
];
Upvotes: 3
Reputation: 26390
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)
Upvotes: 6
Reputation: 122077
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)
Upvotes: 6
Reputation: 1911
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)
Upvotes: 0
Reputation: 66590
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);
Upvotes: 3