Обновить порядок элементов массива, не перемещая его - PullRequest
1 голос
/ 14 июля 2020

У меня есть следующий массив объектов.

[
  { id: 1, title: 't1', order: 0 },
  { id: 2, title: 't1', order: 1 },
  { id: 3, title: 't1', order: 2 },
]

Я хочу несколько раз изменить порядок элементов. В первой попытке.

// move id: 1, fromOrder: 0, toOrder: 2
[
  { id: 1, title: 't1', order: 2 },
  { id: 2, title: 't2', order: 0 },
  { id: 3, title: 't3', order: 1 },
]

Во второй попытке.

// move id: 3, fromOrder: 1, toOrder: 0
[
  { id: 1, title: 't1', order: 2 },
  { id: 2, title: 't2', order: 1 },
  { id: 3, title: 't3', order: 0 },
]

Как видите, суть в том, что я не собираюсь перемещать элемент, я просто хочу обновить атрибут заказа.

Я сделал что-то вроде ниже, но он не работает должным образом.

const reorder = (array, id, oldIndex, newIndex) => {
  const ordered = array
    .map(item => item.order === newIndex ? { ...item, order: oldIndex } : item)
    .map(item => item.id === id ? { ...item, order: newIndex } : item);
  
  return ordered;
};

Ответ на публикацию Разъяснение третьей стороны Пользователь хотел переместить все заказы товаров (включая обертывание), а не просто поменять местами два значения, сохраняя относительные порядки.

Ответы [ 3 ]

2 голосов
/ 14 июля 2020

Наиболее соответствует вашему варианту кода

Все, что вам нужно сделать, это вычислить разницу между начальным и конечным индексами и сместить порядок всех элементов на это значение.

const reorder = (array, id, oldIndex, newIndex) => {
  orderShift = newIndex-oldIndex;
  const ordered = array.map(item => {
    item.order = mod(item.order + orderShift, array.length);
    return item;
  });
  return ordered;
};

Большинство эффективный вариант

Приведенный ниже код является оптимизированной функцией, поскольку вам не нужно указывать идентификатор элемента или какие-либо c индексы, а только то, на сколько нужно сдвинуть.

const reorder = (array, shift) => {
  for (let i=0, len=array.length; i<len; i++) {
    array[i].order = mod(array[i].order + shift, len);
  }
  return array;
};

Самый полезный вариант

Если вы не знаете его текущее местоположение и хотите указать newIndex, то вы можете альтернативно использовать функцию ниже.

const reorder = (array, id, newIndex) => {
  let shift = newIndex - array.find(x => x.id === id).order;
  for (let i=0, len=array.length; i<len; i++) {
    array[i].order = mod(array[i].order + shift, len);
  }
  return array;
};

Дополнительная необходимая функция

Поскольку JavaScript не имеет оператора по модулю (только оператор % «остаток»), я использую эту функцию как быстрый доступ.

// you'll need this mod function in all of the above options
function mod(n, m) {
  return ((n % m) + m) % m;
}
1 голос
/ 14 июля 2020

Я бы просто использовал a для l oop и увеличивал массив, когда вы дойдете до максимума или конца массива, верните его обратно к нулю.

var data = [
  { id: 1, title: 't1', order: 0 },
  { id: 2, title: 't2', order: 1 },
  { id: 3, title: 't3', order: 2 },
  { id: 4, title: 't4', order: 3 },
  { id: 5, title: 't5', order: 4 },
  { id: 6, title: 't6', order: 5 },
  { id: 7, title: 't7', order: 6 },
  { id: 8, title: 't8', order: 7 },
];

const debugIt = array => console.log(array.map(x => `${x.id} - ${x.order}`)); 

const reorder = (array, id, newIndex) => {

  let index = array.findIndex(x => x.id === id);
  var max = array.length - 1;
  for (var i=0; i<array.length; i++) {
    array[index].order = newIndex;
    index++
    newIndex++;
    if (index > max) index = 0;
    if (newIndex > max) newIndex = 0;
  }

};

debugIt(data);
reorder(data, 4, 0);
debugIt(data);
reorder(data, 7, 0);
debugIt(data);
0 голосов
/ 14 июля 2020

Как сказано в удаленном посте, вам не нужно спрашивать oldIndex.

Насколько я понимаю ваш код, вы меняете местами элементы массивов, а не перемещаете их. Что вам нужно сделать, так это уменьшить или увеличить индекс всех элементов между старым и новым индексом:

const reorder = (array, id, newIndex) => {
  const oldIndex = array.findIndex(item => item.id == id);
  const ordered = array
    .map(item =>
      (item.order > oldIndex && item.order <= newIndex) ? // implicit check of oldIndex < newIndex
         { id: 1, title: 't1', order: item.order-1 } :
      (item.order < oldIndex && item.order >= newIndex) ? // implicit check of oldIndex > newIndex
         { id: 1, title: 't1', order: item.order+1 } :
      (item.id == id) ?
         { id: 1, title: 't1', order: newIndex } :
         item
    );
  
  return ordered;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...