Reordenación de matrices


98

Diga, tengo una matriz que se ve así:

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

¿Cómo puedo mover un elemento a otra posición?

Quiero moverme, por ejemplo, {artist:"Lalo Schifrin", title:"Shifting Gears"}hasta el final.

Intenté usar empalme, así:

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

Pero no funciona.


3
¿Qué significa "no funciona" - arroja un error, no cambia nada, cambia su matriz de una manera que no pretendía? Me parece razonable.
Jacob Mattison

Respuestas:


220

La sintaxis de Array.splicees:

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

Dónde:

  • índice es la posición en la matriz de la que desea comenzar a eliminar elementos
  • cuántos es cuántos elementos desea eliminar del índice
  • element1, ..., elementX son elementos que desea insertar desde el índice de posición .

Esto significa que splice()se puede usar para eliminar elementos, agregar elementos o reemplazar elementos en una matriz, según los argumentos que pase.

Tenga en cuenta que devuelve una matriz de los elementos eliminados.

Algo agradable y genérico sería:

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

Entonces solo usa:

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

Diagrama:

Diagrama de algoritmo


17
Esta es una buena respuesta, y el empalme () dentro de un empalme () hace bien el trabajo. Sin embargo, debe tenerse en cuenta que agregar un método move () al prototipo Array se llama "Monkey Patching" y generalmente se considera una mala práctica. stackoverflow.com/questions/5741877/…
Aaron Cicali

20

Si conoce los índices, podría intercambiar fácilmente los elementos, con una función simple como esta:

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

Los índices de matriz son solo propiedades del objeto de matriz, por lo que puede intercambiar sus valores.


Gracias, @CMS. Si cambio las medias, no quiero reemplazar el orden ... Por ejemplo, si selecciono el tercer objeto en la primera posición, quiero intercambiar 1 como 2 y 2 como 3 como 1
Peri

13

Aquí hay una versión inmutable para aquellos que estén interesados:

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

Hola, ¿podrías explicarme los beneficios de esta función sobre la respuesta anterior?
Xogno

1
Esta solución no modifica el elemento original, pero devuelve una nueva matriz con la entrada que se mueve.
chmanie

7

Cambie 2 a 1 como primer parámetro en la llamada de empalme al eliminar el elemento:

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

1
debería ser playlist.splice (2,0, tmp [0]); ¿Correcto?
Crisboot

7

Con ES6 puede hacer algo como esto:

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
Esto intercambia las posiciones de los dos elementos. La pregunta es para reordenar.
POR

5

Siempre puede usar el método de clasificación, si no sabe dónde está el registro en este momento:

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

What aboutreturn +(a.artist == "Lalo Schifrin")
Funkodebat

2
@Funko podrías hacer eso, si prefieres la brevedad a la verbosidad.
Andy E

2

EDITAR: Por favor, consulte la respuesta de Andy, ya que su respuesta fue la primera y esta es solo una extensión

Sé que esta es una pregunta antigua, pero creo que vale la pena incluirla Array.prototype.sort().

Aquí hay un ejemplo de MDN junto con el enlace

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

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

Afortunadamente, no solo funciona con números:

arr.sort([compareFunction])

compareFunction

Especifica una función que define el orden de clasificación. Si se omite, la matriz se ordena según el valor del punto de código Unicode de cada carácter, según la conversión de cadena de cada elemento.

Noté que los está ordenando por nombre:

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

Tenga en cuenta que si se quería ordenarlos por apellido tendría que o bien tienen una clave para ambos first_namey last_name, o hacer un poco de magia de expresiones regulares, que yo no puedo hacer XD

Espero que ayude :)


Esto debería ser una edición o un comentario sobre esta respuesta .
Jared Smith

@JaredSmith ¡Ups! No vi su respuesta. No tengo suficientes puntos o lo que sea para editar su pregunta, y no creo que toda esta información deba agregarse en un comentario. Entonces, hasta que alguien edite su pregunta, simplemente agregaré que esta es una extensión de la respuesta de Andy E (como debería haber hecho).
Jaacko Torus

Creo que está bien ahora :)
Jared Smith

1

Prueba esto:

playlist = playlist.concat(playlist.splice(1, 1));

1

Si solo desea mover un elemento desde una posición arbitraria al final de la matriz, esto debería funcionar:

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

Si desea mover varios elementos desde una posición arbitraria hasta el final, puede hacer:

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

Si desea mover varios elementos de una posición arbitraria a una posición arbitraria, intente:

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

Como solución mutable simple, puede llamar a splice dos veces seguidas:

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

Por otro lado, una solución inmutable simple podría usar slice ya que este método devuelve una copia de una sección de la matriz original sin cambiarla:

const copy = [...playlist.slice(0, INDEX_TO_MOVE - 1), ...playlist.slice(INDEX_TO_MOVE), ...playlist.slice(INDEX_TO_MOVE - 1, INDEX_TO_MOVE)]

-2

Reordenar su trabajo de esta manera

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

Espero que esto funcione


1
¿Qué agrega esto sobre las respuestas existentes?
Jared Smith
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.