Как сделать так, чтобы в выводе не появлялось число 5?

По сути список не сдвинулся — сместились только элементы 6 и 4. Почему функция возвращает сообщения о перемещении для других элементов? <br/> <pre><code>function getMoveMessages(appliedList, draftList) {
  • 30 марта 2026 г. 10:00
Ответы на вопрос 2
Коротко — потому что при сравнении "старого" и "нового" списков простая проверка индексов даёт ложные срабатывания: когда вы вынимаете/вставляете элемент, индексы остальных элементов меняются, и простое сравнение индекса в appliedList и draftList покажет, что они "переместились", хотя их относительный порядок не поменялся.

Что делать — необходимо находить минимальный набор реально перемещённых элементов, а не смотреть на абсолютные индексы. Стандартный приём — сопоставить id элементов (или другой уникальный ключ), построить для draftList массив индексов из appliedList и найти в нём Longest Increasing Subsequence (LIS). Элементы, входящие в LIS, сохранили относительный порядок и фактически не перемещались; остальные — действительно перемещены.

Пример функции на JS, принимающей списки элементов (или id) и возвращающей сообщения о реальных перемещениях:

```js
function getMoveMessages(appliedList, draftList, getId = x => x) {
  // карта id -> исходный индекс
  const idToIndex = new Map(appliedList.map((item, i) => [getId(item), i]));

  // последовательность исходных индексов в порядке draftList; пропускаем новые элементы
  const seq = [];
  const draftIds = [];
  for (const item of draftList) {
    const id = getId(item);
    const idx = idToIndex.get(id);
    if (idx !== undefined) {
      seq.push(idx);
      draftIds.push(id);
    }
  }

  // LIS (по индексам) — стандартный O(n log n) алгоритм с восстановлением
  const n = seq.length;
  const tails = [];           // значение последнего элемента для каждой длины
  const tailsPos = [];        // позиция в seq для каждой длины
  const prev = new Array(n).fill(-1);

  for (let i = 0; i < n; i++) {
    const x = seq[i];
    // lower_bound по tails
    let lo = 0, hi = tails.length;
    while (lo < hi) {
      const mid = (lo + hi) >> 1;
      if (tails[mid] < x) lo = mid + 1; else hi = mid;
    }
    if (lo > 0) prev[i] = tailsPos[lo - 1];
    tails[lo] = x;
    tailsPos[lo] = i;
  }

  // восстановим индексы элементов, входящих в LIS
  let lisIdx = [];
  if (tailsPos.length > 0) {
    let p = tailsPos[tailsPos.length - 1];
    while (p !== -1) {
      lisIdx.push(p);
      p = prev[p];
    }
    lisIdx.reverse();
  }
  const inLIS = new Set(lisIdx.map(i => draftIds[i]));

  // сформируем сообщения: те id, которые есть в appliedList и draftList, но не в LIS
  const messages = [];
  for (let newIndex = 0; newIndex < draftList.length; newIndex++) {
    const id = getId(draftList[newIndex]);
    if (!idToIndex.has(id)) {
      messages.push(`Добавлен ${id} на позицию ${newIndex}`); // опционально: новые элементы
      continue;
    }
    if (!inLIS.has(id)) {
      const oldIndex = idToIndex.get(id);
      messages.push(`Элемент ${id} перемещён с ${oldIndex} на ${newIndex}`);
    }
  }

  // опционально: можно также показать удалённые элементы из appliedList, которых нет в draftList
  for (const item of appliedList) {
    const id = getId(item);
    if (!draftList.some(d => getId(d) === id)) {
      messages.push(`Удалён ${id}`);
    }
  }

  return messages;
}
```

Пример использования:
- если appliedList = [1,2,3,4,5,6] и draftList = [1,2,3,6,5,4], то LIS даст [1,2,3] (или возможно [1,2,3,5] в зависимости), и будут помечены как перемещённые только те элементы, которые реально изменили относительный порядок (в вашем случае — 6 и 4), а 5 не будет показываться, если его относительный порядок не нарушен.

Итог: причина появления "5" — вы сравнивали абсолютные индексы. Решение — сравнивать относительный порядок и использовать LIS, чтобы отличать реальные перемещения от сдвигов, вызванных удалением/вставкой других элементов. Если пришлёте ваш текущий код (полностью), могу показать, как на нём исправить поведение.
тут классическая проблема: по двум массивам нельзя отличить кто «реально» двинулся а кто просто подвинулся. стандартный подход — longest common subsequence между списками, всё что не попало в LCS то и перемещалось. у тебя LCS это <code>[7,5,4,3,2,1]</code> , значит двигалась только 6.
Похожие вопросы