Сортировать сгруппированные массивы по приоритету - PullRequest
2 голосов
/ 06 августа 2020

Простите за плохую формулировку, я даже не могу сформулировать это по-хорошему, поэтому опишу на примерах.

У меня есть набор приоритетов:

const priorities = new Map([
    ['lowest', 1],
    ['low', 2],
    ['high', 3],
    ['highest', 4],
])

У меня есть массив объектов с группами и приоритетами:

const array = [
    {id: 1, priority: 'high'},
    {id: 2, priority: 'lowest'},
    {id: 3, priority: 'highest'},
    {id: 4, group: 1, priority: 'low'},
    {id: 5, group: 2, priority: 'low'},
    {id: 6, group: 2, priority: 'lowest'},
    {id: 7, group: 2, priority: 'low'},
    {id: 8, group: 1, priority: 'high'}
];

И я сгруппировал этот массив в объект с сгруппированными массивами элементов:

const groups = {
    0: [{ id: 1, priority: 'high' }, { id: 2, priority: 'lowest' }, { id: 3, priority: 'highest' }], // have no highest priority for group 0
    1: [{ id: 4, group: 1, priority: 'low' }, { id: 8, group: 1, priority: 'high' }], // high
    2: [{ id: 5, group: 2, priority: 'low' }, { id: 6, group: 2, priority: 'lowest' }, { id: 7, group: 2, priority: 'low' }] // low
};

Приоритет группа (кроме группы 0) это самый высокий приоритет элементов в этой группе. Мне нужно выбрать наивысший приоритет из каждой группы (кроме группы 0) , чтобы отсортировать группы и элементы из группы 0 от highest до lowest, это должно выглядеть как

[<highest by priority item w/o group>, ...<items from highest by priority group>, ... , <lowest by priority items>, <>]

Вообще мне нужна сортировка по group's priority + item without group priority + initial position. Например, результат для текущего исходного массива:

const result = [
    { id: 3, priority: 'highest' },
    { id: 1, priority: 'high' },
    { id: 4, group: 1, priority: 'low' },
    { id: 8, group: 1, priority: 'high' },
    { id: 5, group: 2, priority: 'low' },
    { id: 6, group: 2, priority: 'lowest' },
    { id: 7, group: 2, priority: 'low' },
    { id: 2, priority: 'lowest' },
];

Как я мог это сделать?

1 Ответ

2 голосов
/ 06 августа 2020

Вы можете

  • дать каждому элементу индекс, чтобы узнать их исходный порядок. (Также можно полагаться на стабильность сортировки, но об этом легче рассуждать, если явным образом):

    for (const [i, o] of array.entries()) o.index = i;
    
  • дайте каждой группе ключ для сортировки, который основан на для максимального приоритета и первого элемента:

    const groupIds = Object.keys(groups).filter(g => g != 0);
    groupIds.map(g => {
      let minIndex = Infinity, maxPriority = 0;
      for (const item of groups[g])
        minIndex = Math.min(minIndex, item.index);
        maxPriority = Math.max(maxPriority, priorities.get(item.priority));
      }
      return {group: groups[g], minIndex, maxPriority};
    })
    
  • добавить одну «группу» из одного элемента для каждого элемента без группировки:

    ….concat(groups[0].map(item => {
      return {group: [item], maxPriority: priorities.get(item.priority), minIndex: item.index};
    }))
    
  • перед сортировкой массива групп:

    ….sort((a, b) => b.maxPriority - a.maxPriority || a.minIndex - b.minIndex)
    
  • с последующим объединением их в результат:

    ….flatMap(({group}) => {
      return group.sort((a, b) => a.index - b.index); // might be unnecessary depending on how you built the group arrays
    });
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...