Получить массив отсортированный на основе содержимого другого массива - PullRequest
4 голосов
/ 24 апреля 2019

Как мне отсортировать отсортированный массив allGames, чтобы сначала установить игры?

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

В основном я хочу получить этот заказ:

{ id: 2, name: 'game2' },
{ id: 3, name: 'game3' },
{ id: 1, name: 'game1' },
{ id: 4, name: 'game4' }

Ответы [ 7 ]

6 голосов
/ 24 апреля 2019

Вы можете использовать метод sort и внутри findIndex, а затем проверить, равен ли индекс -1, и отсортировать по результатам.

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)

Вы также можете создавать объекты из установленных игр и сортировать по этому объекту.

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)
6 голосов
/ 24 апреля 2019

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)

Кроме того, я бы предложил сменить модель. Вместо того, чтобы иметь два разных массива, я предлагаю иметь только один и добавить атрибут installed в свои игры. Это сделает вашу жизнь проще:

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)
3 голосов
/ 24 апреля 2019

Я думаю, что это самый быстрый способ решить эту проблему.

 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 )
];
3 голосов
/ 24 апреля 2019

Вот моя попытка:

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);
2 голосов
/ 24 апреля 2019

Критерии для сравнения a и b следующие:

  • Если оба элемента установлены или оба элемента не установлены, то элемент с меньшим идентификатором сначала
  • В противном случае (гарантированно, что один установлен, а другой - нет) сначала устанавливается элемент

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);
2 голосов
/ 24 апреля 2019

Вы можете попробовать следующее.

Во-первых, чтобы повысить производительность, создайте карту с key в виде id и value в виде index в installedGames массиве. Затем отсортируйте первый массив на основе индексов, хранящихся в карте.

Отобразить второй массив и создать массив идентификаторов. Теперь сортируйте первый массив на основе

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);
0 голосов
/ 24 апреля 2019

Вы можете попробовать это

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...