Как я упоминал в моих комментариях, я обнаружил, что это маловероятная структура данных, не получающая ни одного из преимуществ истинно двусвязного списка. Также в комментариях я спрашивал о до против после при вставке или перемещении элемента. В этой версии предполагается, что предполагалось переместить после указанного узла, отметив, где нам также может потребоваться до версий функций.
Справедливое предупреждение, это уродливый императивный код, изменяющий структуры данных волей-неволей внутри своих функций. (Хотя нет, конечно, на границах функций; я не варвар!)
Вы сказали в комментарии, что у вас уже есть функции insert
и delete
. Если это так, вы можете написать простую версию move
так, как я делаю здесь, просто вставив измененную копию удаленного узла после целевого.
Я не пытаюсь разместить вставленный узел в любом конкретном месте в массиве; Из структуры данных я предполагаю, что просто поместить ее в конец не проблема. Если бы это было так, нам бы тоже пришлось начать дурачиться с индексами. Это не сложно, но некрасиво.
В этом коде нет проверки ошибок, оставляя это в качестве упражнения для читателя. Если вы используете идентификатор, которого нет в списке, мы не несем ответственности за то, что происходит. Это может делить на ноль, запускать ракеты или украсть вашего парня. Вы были предупреждены.
// or Ramda's `clone`, or whatever
const clone = (o) => JSON .parse (JSON .stringify (o))
const removeNode = (dll, id) => {
const list = clone (dll)
const byId = (i) => list .find (({id}) => id === i)
const node = byId (id)
const prevNode = node .prev_id ? byId (node .prev_id) : null
const nextNode = node .next_id ? byId (node .next_id) : null
if (prevNode) prevNode .next_id = node .next_id
if (nextNode) nextNode .prev_id = node .prev_id
return list.filter(node => node .id !== id)
}
const insertAfter = (dll, id, item) => {
const list = clone (dll)
const byId = (i) => list .find (({id}) => id === i)
const node = byId (id)
const nextNode = node .next_id ? byId (node .next_id) : null
node .next_id = item .id
if (nextNode) nextNode .prev_id = item .id
return [...list, {
...item,
prev_id: node .id,
next_id: nextNode ? nextNode .id : null
}]
}
const moveAfter = (dll, fromId, afterId) => {
const node = dll .find (({id}) => id == fromId)
return insertAfter (removeNode (dll, fromId), afterId, node)
}
// and insertBefore, moveBefore
const dll = [
{id: '14', prev_id: null, next_id: '41'},
{id: '41', prev_id: '14', next_id: '22'},
{id: '22', prev_id: '41', next_id: '45'},
{id: '45', prev_id: '22', next_id: null},
]
console.log (
moveAfter (dll, '14', '41')
)