Как отсортировать массив объектов, содержащих ссылки на другие объекты, которые должны стоять на первом месте? - PullRequest
0 голосов
/ 02 апреля 2020

Как я могу отсортировать массив объектов, содержащий ссылки на другие объекты в том же массиве, который должен стоять первым?

У меня есть массив объектов, которые нужно отсортировать по двум факторы:

  1. Объект должен появляться после всех его «членов» («члены» являются ссылками на «имя» других объектов в том же массиве).
  2. Затем, если он не может быть отсортирован по вышеуказанным критериям, он должен быть отсортирован в в алфавитном порядке по «имени» .

Например, рассмотрим следующее MVCE :

const example = [
  // This object named "Example 1" should come after its members ("Example 4"):
  {
    name: 'Example 1',
    members: [
      'Example 4',
    ],
  },
  // This object named "Example 2" should come after its members ("Example 1" and "Example 3"):
  {
    name: 'Example 2',
    members: [
      'Example 1',
      'Example 3',
    ],
  },
  // This object named "Example 3" does not have any members, so it does not necessarily need to change position:
  {
    name: 'Example 3',
    members: [],
  },
  // This object named "Example 4" does not have any members, so it does not necessarily need to change position:
  {
    name: 'Example 4',
    members: [],
  },
  // This object named "Example 5" should come after its members ("Example 1"):
  {
    name: 'Example 5',
    members: [
      'Example 1',
    ],
  },
];

// The objects in "example" should also be sorted by "name" ASC, where it can not be sorted by "members".

example.sort((a, b) => {
  if (a.members.includes(b.name) && b.members.includes(a.name)) {
    // Circular Reference: Skip because "a" AND "b" cannot be members of each other at the same time, so no re-ordering needed at the moment:
    return 0;
  } else if (a.members.includes(b.name) && !b.members.includes(a.name)) {
    // "a" includes "b" as a member, so "a" should come after "b":
    return 1;
  } else if (!a.members.includes(b.name) && b.members.includes(a.name)) {
    // "b" includes "a" as a member, so "b" should come after "a":
    return -1;
  } else if (!a.members.includes(b.name) && !b.members.includes(a.name)) {
    // Neither "a" nor "b" include each other as a member, so no re-ordering needed at the moment:
    return 0;
  } else {
    // OTHERWISE, use the secondary sort by "name", where it could not be sorted by "members":
    return a.name.localeCompare(b.name);
  }
});

console.log(example);

Приведенный выше код дает неверный результат :

  1. «Пример 1»
  2. «Пример 3»
  3. «Пример 2»
  4. «Пример 4»
  5. «Пример 5»

Правильное значение , предназначенное результат должен быть:

  1. «Пример 3»
  2. «Пример 4»
  3. «Пример 1»
  4. «Пример 2»
  5. "Пример 5"

Каков наилучший способ сортировки этого массива на основе критериев, которые я перечислил выше?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...