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


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);

Але це не працює.


3
Що означає "не працює" - чи видає помилку, чи нічого не змінює, чи змінює ваш масив способом, яким ви не мали наміру? Мені це здається розумним.
Jacob Mattison

Відповіді:


220

Синтаксис 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
Це хороша відповідь, і сплайсинг () всередині сплайсингу () добре виконує роботу. Однак слід зазначити, що додавання методу move () до прототипу Array називається "Виправлення мавп" і, як правило, вважається поганою практикою. stackoverflow.com/questions/5741877 / ...
Аарон Cicali

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
Peri

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;
  }, []);
}

Привіт, не могли б ви пояснити мені переваги цієї функції над відповіддю вище?
Xogno,

1
Це рішення не змінює вихідний елемент, а повертає новий масив із переміщенням запису.
chmanie

7

Змініть 2 на 1 як перший параметр у виклику сплайсингу при видаленні елемента:

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]

1
Це міняє місцями два елементи. Питання для повторного замовлення.
BY

5

Ви завжди можете використовувати метод сортування, якщо ви не знаєте, де зараз знаходиться запис:

playlist.sort(function (a, b) {
    return a.artist == "Lalo Schifrin" 
               ? 1    // Move it down the list
               : 0;   // Keep it the same
});

А щодо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

Якщо ви хочете перенести лише один елемент із довільної позиції в кінець масиву, це має спрацювати:

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;
}

0

Як просте змінне рішення ви можете викликати сплайсинг двічі поспіль:

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
Що це додає до існуючих відповідей?
Джаред Сміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.