Zmiana kolejności tablic

98

Powiedz, mam tablicę, która wygląda następująco:

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

Jak mogę przenieść element w inne miejsce?

Chcę przejść na przykład {artist:"Lalo Schifrin", title:"Shifting Gears"}do końca.

Próbowałem użyć splotu, na przykład:

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

Ale to nie działa.

Wurlitzer
źródło
3
Co oznacza „nie działa” - czy generuje błąd, czy niczego nie zmienia, czy zmienia tablicę w sposób, którego nie zamierzałeś? Wydaje mi się to rozsądne.
Jacob Mattison,

Odpowiedzi:

222

Składnia Array.spliceto:

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

Gdzie:

  • indeks to pozycja w tablicy, od której chcesz rozpocząć usuwanie elementów
  • howmany to ile elementy chcesz usunąć z indeksu
  • element1, ..., elementX to elementy, które chcesz wstawić z indeksu pozycji .

Oznacza to, że splice()może być używany do usuwania elementów, dodawania elementów lub zamiany elementów w tablicy, w zależności od przekazanych argumentów.

Zauważ, że zwraca tablicę usuniętych elementów.

Coś ładnego i ogólnego byłoby:

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

Następnie po prostu użyj:

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

Diagram:

Schemat algorytmu

Matt
źródło
17
To dobra odpowiedź, a metoda splice () w metodzie splice () dobrze sobie radzi. Należy jednak zauważyć, że dodanie metody move () do prototypu tablicy nazywa się „Monkey Patching” i jest zwykle uznawane za złą praktykę. stackoverflow.com/questions/5741877/…
Aaron Cicali
20

Jeśli znasz indeksy, możesz łatwo zamienić elementy za pomocą prostej funkcji, takiej jak ta:

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"}]

Indeksy tablic są po prostu właściwościami obiektu tablicy, więc możesz zamienić ich wartości.

Christian C. Salvadó
źródło
Dzięki, @CMS. Jeśli mogę zamienić średnimi nie chce zastąpić kolejność ... Na przykład, jeśli wybiorę 3rd obiekt do pozycji 1 st chcę zamiany 1 jako 2 i 2 a 3 w 1
Peri
13

Oto niezmienna wersja dla zainteresowanych:

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
źródło
Cześć, czy mógłbyś mi wyjaśnić zalety tej funkcji w porównaniu z powyższą odpowiedzią?
Xogno
1
To rozwiązanie nie modyfikuje oryginalnego elementu, ale zwraca nową tablicę z przenoszonym wpisem.
chmanie
7

Zmień 2 na 1 jako pierwszy parametr w wywołaniu połączenia podczas usuwania elementu:

var tmp = playlist.splice(1, 1);
playlist.splice(2, 0, tmp[0]);
Trevor
źródło
1
powinno to być playlist.splice (2,0, tmp [0]); Dobrze?
Crisboot
7

Z ES6 możesz zrobić coś takiego:

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
źródło
1
Spowoduje to zamianę pozycji dwóch elementów. Pytanie jest do ponownego zamówienia.
PRZEZ
5

Zawsze możesz użyć metody sortowania, jeśli nie wiesz, gdzie obecnie znajduje się rekord:

playlist.sort(function (a, b) {
    return a.artist == "Lalo Schifrin" 
               ? 1    // Move it down the list
               : 0;   // Keep it the same
});
Andy E.
źródło
1
A co zreturn +(a.artist == "Lalo Schifrin")
Funkodebat
2
@Funko, możesz to zrobić, jeśli wolisz zwięzłość od gadatliwości.
Andy E
2

EDYCJA: Sprawdź odpowiedź Andy'ego ponieważ jego odpowiedź była pierwsza i jest to wyłącznie jego rozszerzenie

Wiem, że to stare pytanie, ale myślę, że warto je uwzględnić Array.prototype.sort() .

Oto przykład z MDN wraz z linkiem

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

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

Na szczęście działa nie tylko z liczbami:

arr.sort([compareFunction])

compareFunction

Określa funkcję, która definiuje porządek sortowania. W przypadku pominięcia tablica jest sortowana zgodnie z wartością punktu kodowego Unicode każdego znaku, zgodnie z konwersją ciągów każdego elementu.

Zauważyłem, że zamawiasz je po imieniu:

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

zwróć uwagę, że jeśli chcesz zamówić je według nazwiska, musisz mieć klucz do obu first_name& last_namelub użyć magii wyrażeń regularnych, czego nie mogę zrobić XD

Mam nadzieję, że to pomoże :)

Jaacko Torus
źródło
Powinna to być zmiana lub komentarz do tej odpowiedzi .
Jared Smith
@JaredSmith Oops! Nie widziałem jego odpowiedzi. Nie mam wystarczającej liczby punktów lub czegokolwiek, aby edytować jego pytanie i nie sądzę, aby wszystkie te informacje zostały dodane w komentarzu. Więc dopóki ktoś nie zmieni swojego pytania, po prostu dodam, że jest to rozszerzenie odpowiedzi Andy'ego E. (tak jak powinienem zrobić).
Jaacko Torus
Myślę, że teraz jest dobrze :)
Jared Smith
1

Spróbuj tego:

playlist = playlist.concat(playlist.splice(1, 1));
JamieJag
źródło
1

Jeśli chcesz przenieść tylko jeden element z dowolnej pozycji na koniec tablicy, powinno to zadziałać:

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

Jeśli chcesz przenieść wiele elementów z dowolnej pozycji na koniec, możesz:

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

Jeśli chcesz przenieść wiele elementów z dowolnej pozycji do dowolnej pozycji, spróbuj:

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;
}
Okonomiyaki3000
źródło
0

Jako proste, zmienne rozwiązanie możesz wywołać splice dwa razy z rzędu:

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

Z drugiej strony, proste niezmienne rozwiązanie mogłoby użyć slice, ponieważ ta metoda zwraca kopię sekcji z oryginalnej tablicy bez jej zmiany:

const copy = [...playlist.slice(0, INDEX_TO_MOVE - 1), ...playlist.slice(INDEX_TO_MOVE), ...playlist.slice(INDEX_TO_MOVE - 1, INDEX_TO_MOVE)]
David
źródło
-2

Zmień kolejność jego pracy w ten sposób

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

Mam nadzieję, że to zadziała

Peri
źródło
1
Co to dodaje do istniejących odpowiedzi?
Jared Smith