Переупорядочивание массивов

98

Скажем, у меня есть массив, который выглядит так:

var playlist = [
    {artist:"Herbie Hancock", title:"Thrust"},
    {artist:"Lalo Schifrin", title:"Shifting Gears"},
    {artist:"Faze-O", title:"Riding High"}
];

Как я могу переместить элемент в другую позицию?

Я хочу переехать, например, {artist:"Lalo Schifrin", title:"Shifting Gears"} до конца.

Я пробовал использовать сращивание, вот так:

var tmp = playlist.splice(2,1);
playlist.splice(2,0,tmp);

Но не работает.

Wurlitzer
источник
3
Что означает «не работает» - выдаёт ли он ошибку, ничего не меняет, меняет ли массив так, как вы не планировали? Мне это кажется разумным.
Джейкоб Мэттисон,

Ответы:

222

Синтаксис Array.splice:

yourArray.splice(index, howmany, element1, /*.....,*/ elementX);

Куда:

  • index - это позиция в массиве, из которой вы хотите начать удаление элементов
  • howmany , сколько элементов вы хотите удалить из индекса
  • element1, ..., elementX - это элементы, которые вы хотите вставить из индекса позиции .

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

Обратите внимание, что он возвращает массив удаленных элементов.

Что-нибудь приятное и общее было бы:

Array.prototype.move = function (from, to) {
  this.splice(to, 0, this.splice(from, 1)[0]);
};

Тогда просто используйте:

var ar = [1,2,3,4,5];
ar.move(0,3);
alert(ar) // 2,3,4,1,5

Диаграмма:

Схема алгоритма

Мэтт
источник
17
Это хороший ответ, и splice () внутри splice () хорошо справляется со своей задачей. Однако следует отметить, что добавление метода move () к прототипу Array называется «исправлением обезьяны» и обычно считается плохой практикой. stackoverflow.com/questions/5741877/…
Аарон Чикали
20

Если вы знаете индексы, вы можете легко поменять местами элементы с помощью такой простой функции:

function swapElement(array, indexA, indexB) {
  var tmp = array[indexA];
  array[indexA] = array[indexB];
  array[indexB] = tmp;
}

swapElement(playlist, 1, 2);
// [{"artist":"Herbie Hancock","title":"Thrust"},
//  {"artist":"Faze-O","title":"Riding High"},
//  {"artist":"Lalo Schifrin","title":"Shifting Gears"}]

Индексы массива - это просто свойства объекта массива, поэтому вы можете поменять местами его значения.

Кристиан К. Сальвадо
источник
Спасибо, @CMS. Если я поменяю местами, значит, не хочу заменять порядок ... Например, если я выберу 3-й объект на 1-ю позицию, я хочу поменять местами 1 как 2 и 2 как 3 как 1
Пери,
13

Вот неизменная версия для тех, кому интересно:

function immutableMove(arr, from, to) {
  return arr.reduce((prev, current, idx, self) => {
    if (from === to) {
      prev.push(current);
    }
    if (idx === from) {
      return prev;
    }
    if (from < to) {
      prev.push(current);
    }
    if (idx === to) {
      prev.push(self[from]);
    }
    if (from > to) {
      prev.push(current);
    }
    return prev;
  }, []);
}
Chmanie
источник
Привет, не могли бы вы объяснить мне преимущества этой функции по сравнению с ответом выше?
Xogno
1
Это решение не изменяет исходный элемент, а возвращает новый массив с перемещаемой записью.
chmanie 04
7

Измените 2 на 1 в качестве первого параметра в вызове splice при удалении элемента:

var tmp = playlist.splice(1, 1);
playlist.splice(2, 0, tmp[0]);
Тревор
источник
1
это должен быть playlist.splice (2,0, tmp [0]); Правильно?
Crisboot
7

С ES6 вы можете сделать что-то вроде этого:

const swapPositions = (array, a ,b) => {
  [array[a], array[b]] = [array[b], array[a]]
}

let array = [1,2,3,4,5];
swapPositions(array,0,1);

/// => [2, 1, 3, 4, 5]
arthurDent
источник
1
Это меняет местами позиции двух элементов. Вопрос на повторный заказ.
BY
5

Вы всегда можете использовать метод сортировки, если не знаете, где сейчас находится запись:

playlist.sort(function (a, b) {
    return a.artist == "Lalo Schifrin" 
               ? 1    // Move it down the list
               : 0;   // Keep it the same
});
Энди Э
источник
1
Что насчетreturn +(a.artist == "Lalo Schifrin")
Funkodebat
2
@Funko, вы могли бы это сделать, если вы предпочитаете краткость многословию.
Andy E
2

РЕДАКТИРОВАТЬ: пожалуйста, проверьте ответ Энди поскольку его ответ пришел первым, и это исключительно расширение его

Я знаю, что это старый вопрос, но я думаю, что стоит включить Array.prototype.sort() .

Вот пример из MDN со ссылкой

var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
  return a - b;
});
console.log(numbers);

// [1, 2, 3, 4, 5]

К счастью, это работает не только с числами:

arr.sort([compareFunction])

compareFunction

Задает функцию, определяющую порядок сортировки. Если опущено, массив сортируется в соответствии со значением кодовой точки Unicode каждого символа, в соответствии с преобразованием строки каждого элемента.

Я заметил, что вы заказываете их по имени:

let playlist = [
    {artist:"Herbie Hancock", title:"Thrust"},
    {artist:"Lalo Schifrin", title:"Shifting Gears"},
    {artist:"Faze-O", title:"Riding High"}
];

// sort by name
playlist.sort((a, b) => {
  if(a.artist < b.artist) { return -1; }
  if(a.artist > b.artist) { return  1; }

  // else names must be equal
  return 0;
});

обратите внимание, что если вы хотите упорядочить их по фамилии, вам понадобится ключ для обоих first_name&last_name либо использовать магию регулярных выражений, которую я не могу сделать XD

Надеюсь, это поможет :)

Яако Торус
источник
Это должно быть изменение или комментарий к этому ответу .
Джаред Смит
@JaredSmith Ой! Я не видел его ответа. У меня недостаточно очков или чего-то еще, чтобы отредактировать его вопрос, и я не думаю, что всю эту информацию нужно добавлять в комментарий. Поэтому, пока кто-то не отредактирует свой вопрос, я просто добавлю, что это расширение ответа Энди Э (как будто я должен был сделать).
Jaacko Torus
Думаю, сейчас все в порядке :)
Джаред Смит
1

Попробуй это:

playlist = playlist.concat(playlist.splice(1, 1));
ДжеймиДжаг
источник
1

Если вы хотите переместить только один элемент из произвольной позиции в конец массива, это должно сработать:

function toEnd(list, position) {
    list.push(list.splice(position, 1));
    return list;
}

Если вы хотите переместить несколько элементов из произвольной позиции в конец, вы можете сделать:

function toEnd(list, from, count) {
    list.push.apply(list, list.splice(from, count));
    return list;
}

Если вы хотите переместить несколько элементов из произвольной позиции в произвольную позицию, попробуйте:

function move(list, from, count, to) {
    var args = [from > to ? to : to - count, 0];
    args.push.apply(args, list.splice(from, count));
    list.splice.apply(list, args);

    return list;
}
Окономияки3000
источник
0

В качестве простого изменяемого решения вы можете вызвать splice дважды подряд:

playlist.splice(playlist.length - 1, 1, ...playlist.splice(INDEX_TO_MOVE, 1))

С другой стороны, простое неизменяемое решение может использовать срез, поскольку этот метод возвращает копию раздела из исходного массива, не изменяя его:

const copy = [...playlist.slice(0, INDEX_TO_MOVE - 1), ...playlist.slice(INDEX_TO_MOVE), ...playlist.slice(INDEX_TO_MOVE - 1, INDEX_TO_MOVE)]
Дэвид
источник
-2

Изменить порядок работы таким образом

 var tmpOrder = playlist[oldIndex];
    playlist.splice(oldIndex, 1);
    playlist.splice(newIndex, 0, tmpOrder);

Я надеюсь это сработает

Пери
источник
1
Что это добавляет к существующим ответам?
Джаред Смит