repetidos objetos objects matriz especifico eliminar elementos elemento buscar array javascript arrays

objetos - javascript indexof array of objects



Mueva un elemento de matriz de una posiciĆ³n de matriz a otra (20)

Me resulta difícil descubrir cómo mover un elemento de matriz. Por ejemplo, dado lo siguiente:

var arr = [ ''a'', ''b'', ''c'', ''d'', ''e''];

¿Cómo puedo escribir una función para mover ''d'' antes de ''b'' ?

O ''a'' después de ''c'' ?

Después de la mudanza, los índices del resto de los elementos deben actualizarse. Esto significa que en el primer ejemplo después del movimiento arr [0] sería = ''a'', arr [1] = ''d'' arr [2] = ''b'', arr [3] = ''c'', arr [4] = ''mi''

Parece que debería ser bastante simple, pero no puedo rodearlo con la cabeza.


El método splice () agrega / elimina elementos a / desde una matriz y devuelve los elementos eliminados .

Nota: Este método cambia la matriz original. / w3schools /

Array.prototype.move = function(from,to){ this.splice(to,0,this.splice(from,1)[0]); return this; }; var arr = [ ''a'', ''b'', ''c'', ''d'', ''e'']; arr.move(3,1);//["a", "d", "b", "c", "e"] var arr = [ ''a'', ''b'', ''c'', ''d'', ''e'']; arr.move(0,2);//["b", "c", "a", "d", "e"]

como la función es chainable esto funciona también:

alert(arr.move(0,2).join('',''));

demo aquí


Array.move.js

Resumen

Mueve elementos dentro de una matriz, devolviendo una matriz que contiene los elementos movidos.

Sintaxis

array.move(index, howMany, toIndex);

Parámetros

índice : índice al que mover elementos. Si es negativo, el índice comenzará desde el final.

howMany : Número de elementos a mover desde el índice .

Índice de índice: índice de la matriz en la que se colocan los elementos movidos. Si es negativo, toIndex comenzará desde el final.

Uso

array = ["a", "b", "c", "d", "e", "f", "g"]; array.move(3, 2, 1); // returns ["d","e"] array; // returns ["a", "d", "e", "b", "c", "f", "g"]

Relleno de polietileno

Array.prototype.move || Object.defineProperty(Array.prototype, "move", { value: function (index, howMany, toIndex) { var array = this, index = parseInt(index) || 0, index = index < 0 ? array.length + index : index, toIndex = parseInt(toIndex) || 0, toIndex = toIndex < 0 ? array.length + toIndex : toIndex, toIndex = toIndex <= index ? toIndex : toIndex <= index + howMany ? index : toIndex - howMany, moved; array.splice.apply(array, [toIndex, 0].concat(moved = array.splice(index, howMany))); return moved; } });


Aquí está mi solución ES6 de línea única con un parámetro opcional activado.

if (typeof Array.prototype.move === "undefined") { Array.prototype.move = function(from, to, on = 1) { this.splice(to, 0, ...this.splice(from, on)) } }

Adaptación de la primera solución propuesta por digiguru

El parámetro on es el número de elementos a partir from que desea mover.


Aquí hay un forro que encontré en JSPerf ...

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

que es impresionante de leer, pero si desea rendimiento (en pequeños conjuntos de datos) intente ...

Array.prototype.move2 = function(pos1, pos2) { // local variables var i, tmp; // cast input parameters to integers pos1 = parseInt(pos1, 10); pos2 = parseInt(pos2, 10); // if positions are different and inside array if (pos1 !== pos2 && 0 <= pos1 && pos1 <= this.length && 0 <= pos2 && pos2 <= this.length) { // save element from position 1 tmp = this[pos1]; // move element down and shift other elements up if (pos1 < pos2) { for (i = pos1; i < pos2; i++) { this[i] = this[i + 1]; } } // move element up and shift other elements down else { for (i = pos1; i > pos2; i--) { this[i] = this[i - 1]; } } // put element from position 1 to destination this[pos2] = tmp; } }

No puedo tomar ningún crédito, todo debería ir a Richard Scarrott . Supera el método basado en el empalme para conjuntos de datos más pequeños en esta prueba de rendimiento . Sin embargo, es significativamente más lento en conjuntos de datos más grandes, como señala Darwayne .


Como una adición a la excelente respuesta de Reid (y porque no puedo comentar); Puede usar el módulo para hacer que tanto los índices negativos como los índices demasiado grandes "rueden":

function array_move(arr, old_index, new_index) { new_index =((new_index % arr.length) + arr.length) % arr.length; arr.splice(new_index, 0, arr.splice(old_index, 1)[0]); return arr; // for testing } // returns [2, 1, 3] console.log(array_move([1, 2, 3], 0, 1));


El método de splice de Array podría ayudar: splice

Solo tenga en cuenta que puede ser relativamente caro, ya que tiene que volver a indexar activamente la matriz.


Esta versión no es ideal para todos los propósitos, y no a todos les gustan las expresiones de coma, pero aquí hay una sola frase que es una expresión pura, creando una copia nueva:

Object.defineProperty(Array.prototype, ''immutableMove'', { enumerable: false, value: function (old_index, new_index) { var copy = Object.assign([], this) if (new_index >= copy.length) { var k = new_index - copy.length; while ((k--) + 1) { copy.push(undefined); } } copy.splice(new_index, 0, copy.splice(old_index, 1)[0]); return copy } }); //how to use it myArray=[0, 1, 2, 3, 4]; myArray=myArray.immutableMove(2, 4); console.log(myArray); //result: 0, 1, 3, 4, 2

Una versión ligeramente mejorada en el rendimiento devuelve la matriz de entrada si no se necesita un movimiento, todavía está bien para uso inmutable, ya que la matriz no cambiará, y aún es una expresión pura:

const move = (from, to, ...a) => (a.splice(to, 0, ...a.splice(from, 1)), a)

La invocación de cualquiera de ellas es

const move = (from, to, ...a) => from === to ? a : (a.splice(to, 0, ...a.splice(from, 1)), a)

es decir, se basa en la difusión para generar una copia nueva. El uso de un move arity 3 fijo pondría en peligro la propiedad de una sola expresión, la naturaleza no destructiva o el beneficio de rendimiento del splice . Nuevamente, es más un ejemplo que cumple algunos criterios que una sugerencia para el uso en producción.


Esto se basa en la solución de @ Reid. Excepto:

  • No estoy cambiando el prototipo Array .
  • Mover un elemento fuera de los límites a la derecha no crea elementos no undefined , solo mueve el elemento a la posición más a la derecha.

Función:

function move(array, oldIndex, newIndex) { if (newIndex >= array.length) { newIndex = array.length - 1; } array.splice(newIndex, 0, array.splice(oldIndex, 1)[0]); return array; }

Pruebas unitarias:

describe(''ArrayHelper'', function () { it(''Move right'', function () { let array = [1, 2, 3]; arrayHelper.move(array, 0, 1); assert.equal(array[0], 2); assert.equal(array[1], 1); assert.equal(array[2], 3); }) it(''Move left'', function () { let array = [1, 2, 3]; arrayHelper.move(array, 1, 0); assert.equal(array[0], 2); assert.equal(array[1], 1); assert.equal(array[2], 3); }); it(''Move out of bounds to the left'', function () { let array = [1, 2, 3]; arrayHelper.move(array, 1, -2); assert.equal(array[0], 2); assert.equal(array[1], 1); assert.equal(array[2], 3); }); it(''Move out of bounds to the right'', function () { let array = [1, 2, 3]; arrayHelper.move(array, 1, 4); assert.equal(array[0], 1); assert.equal(array[1], 3); assert.equal(array[2], 2); }); });


He implementado una solución ECMAScript 6 inmutable basada en la respuesta de @Merc aquí:

const moveItemInArrayFromIndexToIndex = (array, fromIndex, toIndex) => { if (fromIndex === toIndex) return array; const newArray = [...array]; const target = newArray[fromIndex]; const inc = toIndex < fromIndex ? -1 : 1; for (let i = fromIndex; i !== toIndex; i += inc) { newArray[i] = newArray[i + inc]; } newArray[toIndex] = target; return newArray; };

Los nombres de las variables se pueden acortar, solo se usan los largos para que el código pueda explicarse.


Me gusta de esta manera. Funciona, es rápido y elegante.

function arraymove(arr, fromIndex, toIndex) { var element = arr[fromIndex]; arr.splice(fromIndex, 1); arr.splice(toIndex, 0, element); }

Nota: siempre recuerde verificar los límites de su matriz.


Mi 2c. Fácil de leer, funciona, es rápido, no crea nuevos arreglos.

function move(array, from, to) { if( to === from ) return array; var target = array[from]; var increment = to < from ? -1 : 1; for(var k = from; k != to; k += increment){ array[k] = array[k + increment]; } array[to] = target; return array; }


Necesitaba un método de movimiento inmutable (uno que no cambiara la matriz original), así que adapté la respuesta aceptada de @ Reid para usar simplemente Object.assign para crear una copia de la matriz antes de hacer el empalme.

Array.prototype.immutableMove = function (old_index, new_index) { var copy = Object.assign([], this); if (new_index >= copy.length) { var k = new_index - copy.length; while ((k--) + 1) { copy.push(undefined); } } copy.splice(new_index, 0, copy.splice(old_index, 1)[0]); return copy; };

Aquí hay un jsfiddle que lo muestra en acción .


Obtuve esta idea de @Reid de empujar algo en el lugar del elemento que se debe mover para mantener constante el tamaño de la matriz. Eso simplifica los cálculos. Además, empujar un objeto vacío tiene los beneficios adicionales de poder buscarlo de manera única más adelante. Esto funciona porque dos objetos no son iguales hasta que se refieren al mismo objeto.

({}) == ({}); // false

Así que aquí está la función que toma en la matriz de origen, y la fuente, los índices de destino. Puede agregarlo al Array.prototype si es necesario.

function moveObjectAtIndex(array, sourceIndex, destIndex) { var placeholder = {}; // remove the object from its initial position and // plant the placeholder object in its place to // keep the array length constant var objectToMove = array.splice(sourceIndex, 1, placeholder)[0]; // place the object in the desired position array.splice(destIndex, 0, objectToMove); // take out the temporary object array.splice(array.indexOf(placeholder), 1); }


Puede implementar algunos cálculos básicos y crear una función universal para mover el elemento de matriz de una posición a otra.

Para JavaScript se ve así:

function magicFunction (targetArray, indexFrom, indexTo) { targetElement = targetArray[indexFrom]; magicIncrement = (indexTo - indexFrom) / Math.abs (indexTo - indexFrom); for (Element = indexFrom; Element != indexTo; Element += magicIncrement){ targetArray[Element] = targetArray[Element + magicIncrement]; } targetArray[indexTo] = targetElement; }

Echa un vistazo a "elementos de matriz en movimiento" en "gloommatter" para obtener una explicación detallada.

http://www.gloommatter.com/DDesign/programming/moving-any-array-elements-universal-function.html


Se dice que en muchos lugares ( agregar funciones personalizadas en Array.prototype ) jugar con el prototipo Array podría ser una mala idea, de todos modos, combiné lo mejor de varias publicaciones, vine con esto, usando el Javascript moderno:

const shuffled = move(fromIndex, toIndex, ...list)

La esperanza puede ser de utilidad para cualquiera.


Si desea una versión en npm, array-move es la más cercana a esta respuesta, aunque no es la misma implementación. Vea su sección de uso para más detalles. La versión anterior de esta respuesta (que modificó Array.prototype.move) se puede encontrar en npm en array.prototype.move .

Tuve bastante éxito con esta función:

function array_move(arr, old_index, new_index) { if (new_index >= arr.length) { var k = new_index - arr.length + 1; while (k--) { arr.push(undefined); } } arr.splice(new_index, 0, arr.splice(old_index, 1)[0]); return arr; // for testing }; // returns [2, 1, 3] console.log(array_move([1, 2, 3], 0, 1));

Tenga en cuenta que la última return es simplemente para fines de prueba: el splice realiza operaciones en la matriz en el lugar, por lo que no es necesario realizar una devolución. Por extensión, este move es una operación in situ. Si quiere evitar eso y devolver una copia, use slice .

Pasando por el código:

  1. Si new_index es mayor que la longitud de la matriz, queremos (supongo) que la matriz se rellene correctamente con nuevos s undefined . Este pequeño fragmento maneja esto presionando undefined en la matriz hasta que tengamos la longitud adecuada.
  2. Luego, en arr.splice(old_index, 1)[0] , arr.splice(old_index, 1)[0] el elemento antiguo. splice devuelve el elemento que fue empalmado, pero está en una matriz. En nuestro ejemplo anterior, esto fue [1] . Entonces tomamos el primer índice de esa matriz para obtener el 1 bruto allí.
  3. Luego usamos splice para insertar este elemento en el lugar de new_index. Ya que new_index > arr.length la matriz anterior si new_index > arr.length , probablemente aparecerá en el lugar correcto, a menos que hayan hecho algo extraño, como pasar un número negativo.

Una versión más elegante para tener en cuenta los índices negativos:

function array_move(arr, old_index, new_index) { while (old_index < 0) { old_index += arr.length; } while (new_index < 0) { new_index += arr.length; } if (new_index >= arr.length) { var k = new_index - arr.length + 1; while (k--) { arr.push(undefined); } } arr.splice(new_index, 0, arr.splice(old_index, 1)[0]); return arr; // for testing purposes }; // returns [1, 3, 2] console.log(array_move([1, 2, 3], -1, -2));

Lo que debería tener en cuenta cosas como array_move([1, 2, 3], -1, -2) correctamente (mover el último elemento al segundo al último lugar). El resultado para eso debe ser [1, 3, 2] .

De cualquier manera, en tu pregunta original, harías array_move(arr, 0, 2) para después de c . Para d antes de b , harías array_move(arr, 3, 1) .


Terminé combinando dos de estos para trabajar un poco mejor al mover distancias pequeñas y grandes. Obtengo resultados bastante consistentes, pero esto podría ser ajustado un poco por alguien más inteligente que yo para trabajar de manera diferente para diferentes tamaños, etc.

El uso de algunos de los otros métodos para mover objetos a pequeñas distancias fue significativamente más rápido (x10) que usar el empalme. Sin embargo, esto podría cambiar dependiendo de la longitud de la matriz, pero es cierto para matrices grandes.

function ArrayMove(array, from, to) { if ( Math.abs(from - to) > 60) { array.splice(to, 0, array.splice(from, 1)[0]); } else { // works better when we are not moving things very far var target = array[from]; var inc = (to - from) / Math.abs(to - from); var current = from; for (; current != to; current += inc) { array[current] = array[current + inc]; } array[to] = target; } }

http://jsperf.com/arraymove-many-sizes


Un enfoque sería crear una nueva matriz con las piezas en el orden que desee, utilizando el método de división.

Ejemplo

var arr = [ ''a'', ''b'', ''c'', ''d'', ''e'']; var arr2 = arr.slice(0,1).concat( [''d''] ).concat( arr.slice(2,4) ).concat( arr.slice(4) );

  • arr.slice (0,1) te da [''a'']
  • arr.slice (2,4) te da [''b'', ''c'']
  • arr.slice (4) te da [''e'']

Usé la buena respuesta de @Reid , pero luché para mover un elemento desde el final de una matriz un paso más allá, hasta el principio (como en un bucle ). Por ejemplo, [''a'', ''b'', ''c''] debería convertirse en [''c'', ''a'', ''b''] llamando a .move (2,3)

Logré esto cambiando el caso para new_index> = this.length.

Array.prototype.move = function (old_index, new_index) { console.log(old_index + " " + new_index); while (old_index < 0) { old_index += this.length; } while (new_index < 0) { new_index += this.length; } if (new_index >= this.length) { new_index = new_index % this.length; } this.splice(new_index, 0, this.splice(old_index, 1)[0]); return this; // for testing purposes };


Array.prototype.moveUp = function (value, by) { var index = this.indexOf(value), newPos = index - (by || 1); if (index === -1) throw new Error("Element not found in array"); if (newPos < 0) newPos = 0; this.splice(index, 1); this.splice(newPos, 0, value); }; Array.prototype.moveDown = function (value, by) { var index = this.indexOf(value), newPos = index + (by || 1); if (index === -1) throw new Error("Element not found in array"); if (newPos >= this.length) newPos = this.length; this.splice(index, 1); this.splice(newPos, 0, value); }; var arr = [''banana'', ''curyWurst'', ''pc'', ''remembaHaruMembaru'']; alert(''withiout changes= ''+arr[0]+'' ||| ''+arr[1]+'' ||| ''+arr[2]+'' ||| ''+arr[3]); arr.moveDown(arr[2]); alert(''third word moved down= ''+arr[0] + '' ||| '' + arr[1] + '' ||| '' + arr[2] + '' ||| '' + arr[3]); arr.moveUp(arr[2]); alert(''third word moved up= ''+arr[0] + '' ||| '' + arr[1] + '' ||| '' + arr[2] + '' ||| '' + arr[3]);

http://plnkr.co/edit/JaiAaO7FQcdPGPY6G337?p=preview