objeto - multiplicar elementos de un array javascript
Recorrer la matriz y eliminar elementos, sin romper el bucle (12)
Tengo lo siguiente para bucle, y cuando uso splice()
para eliminar un elemento, obtengo que los ''segundos'' no están definidos. Podría verificar si está indefinido, pero creo que probablemente haya una forma más elegante de hacerlo. El deseo es simplemente eliminar un elemento y seguir adelante.
for (i = 0, len = Auction.auctions.length; i < len; i++) {
auction = Auction.auctions[i];
Auction.auctions[i][''seconds''] --;
if (auction.seconds < 0) {
Auction.auctions.splice(i, 1);
}
}
Aquí hay otro ejemplo para el uso correcto del empalme. Este ejemplo está a punto de eliminar ''atributo'' de ''matriz''.
for (var i = array.length; i--;) {
if (array[i] === ''attribute'') {
array.splice(i, 1);
}
}
Este es un problema bastante común. La solución es hacer un bucle hacia atrás:
for (var i = Auction.auctions.length - 1; i >= 0; i--) {
Auction.auctions[i].seconds--;
if (Auction.auctions[i].seconds < 0) {
Auction.auctions.splice(i, 1);
}
}
No importa si los estás sacando del final porque los índices se conservarán cuando retrocedas.
Intente retransmitir una matriz en newArray cuando haga bucles:
var auctions = Auction.auctions;
var auctionIndex;
var auction;
var newAuctions = [];
for (
auctionIndex = 0;
auctionIndex < Auction.auctions.length;
auctionIndex++) {
auction = auctions[auctionIndex];
if (auction.seconds >= 0) {
newAuctions.push(
auction);
}
}
Auction.auctions = newAuctions;
La matriz se está volviendo a indexar cuando haces un .splice()
, lo que significa que .splice()
un índice cuando se elimina uno, y tu .length
almacenado en caché está obsoleto.
Para solucionarlo, necesitarías disminuir i
después de un .splice()
, o simplemente iterar a la inversa ...
var i = Auction.auctions.length
while (i--) {
...
if (...) {
Auction.auctions.splice(i, 1);
}
}
De esta manera, la nueva indexación no afecta al siguiente elemento de la iteración, ya que la indexación afecta solo a los elementos desde el punto actual hasta el final de la matriz, y el siguiente elemento de la iteración es más bajo que el punto actual.
Otra solución simple para digerir una serie de elementos una vez:
while(Auction.auctions.length){
// From first to last...
var auction = Auction.auctions.shift();
// From last to first...
var auction = Auction.auctions.pop();
// Do stuff with auction
}
Recalcular la longitud cada vez a través del bucle en lugar de solo al principio, por ejemplo:
for (i = 0; i < Auction.auctions.length; i++) {
auction = Auction.auctions[i];
Auction.auctions[i][''seconds''] --;
if (auction.seconds < 0) {
Auction.auctions.splice(i, 1);
i--; //decrement
}
}
De esa manera no excederás los límites.
EDITAR: añade una disminución en la sentencia if.
Si bien su pregunta es sobre la eliminación de elementos de la matriz que se está iterando y no sobre la eliminación de elementos (además de algún otro procesamiento) de manera eficiente, creo que uno debería reconsiderarlo si se encuentra en una situación similar.
La complejidad algorítmica de este enfoque es O(n^2)
como función de empalme y el bucle for itera sobre la matriz (la función de empalme desplaza todos los elementos de la matriz en el peor de los casos). En su lugar, simplemente puede empujar los elementos requeridos a la nueva matriz y luego simplemente asignar esa matriz a la variable deseada (sobre la cual se iteró).
var newArray = [];
for (var i = 0, len = Auction.auctions.length; i < len; i++) {
auction = Auction.auctions[i];
auction.seconds--;
if (!auction.seconds < 0) {
newArray.push(auction);
}
}
Auction.auctions = newArray;
Desde ES2015 podemos usar Array.prototype.filter
para ajustarlo todo en una línea:
Auction.auctions = Auction.auctions.filter(auction => --auction.seconds >= 0);
Si está utilizando ES6 +, ¿por qué no usa el método Array.filter?
Auction.auctions = Auction.auctions.filter((auction) => {
auction[''seconds''] --;
return (auction.seconds > 0)
})
Tenga en cuenta que la modificación del elemento de la matriz durante la iteración del filtro solo funciona para los objetos y no funcionará para la matriz de valores primitivos.
Solo puedes mirar y usar shift()
Ya hay muchas respuestas maravillosas en este hilo. Sin embargo, quería compartir mi experiencia cuando intenté resolver "eliminar el elemento nth de la matriz" en el contexto de ES5.
Las matrices de JavaScript tienen diferentes métodos para agregar / eliminar elementos de inicio o fin. Estos son:
arr.push(ele) - To add element(s) at the end of the array
arr.unshift(ele) - To add element(s) at the beginning of the array
arr.pop() - To remove last element from the array
arr.shift() - To remove first element from the array
Esencialmente, ninguno de los métodos anteriores se puede usar directamente para eliminar el elemento nth de la matriz.
Un hecho que vale la pena notar es que esto contrasta con el uso del iterador java, en el cual es posible eliminar el elemento nth para una colección mientras se realiza la iteración.
Básicamente, esto nos deja con un solo método de matriz Array.splice
para realizar la eliminación del elemento nth (también hay otras cosas que podría hacer con estos métodos, pero en el contexto de esta pregunta me estoy centrando en la eliminación de elementos):
Array.splice(index,1) - removes the element at the index
Aquí está el código copiado de la respuesta original (con comentarios):
var arr = ["one", "two", "three", "four"];
var i = arr.length; //initialize counter to array length
while (i--) //decrement counter else it would run into IndexOutBounds exception
{
if (arr[i] === "four" || arr[i] === "two") {
//splice modifies the original array
arr.splice(i, 1); //never runs into IndexOutBounds exception
console.log("Element removed. arr: ");
} else {
console.log("Element not removed. arr: ");
}
console.log(arr);
}
Otro método digno de mención es Array.slice
. Sin embargo, el tipo de retorno de este método son los elementos eliminados. Además esto no modifica la matriz original. Fragmento de código modificado de la siguiente manera:
var arr = ["one", "two", "three", "four"];
var i = arr.length; //initialize counter to array length
while (i--) //decrement counter
{
if (arr[i] === "four" || arr[i] === "two") {
console.log("Element removed. arr: ");
console.log(arr.slice(i, i + 1));
console.log("Original array: ");
console.log(arr);
}
}
Dicho esto, todavía podemos usar Array.slice
para eliminar el elemento nth de la siguiente manera y, como puede observar, hay mucho más código (por lo tanto, ineficiente)
var arr = ["one", "two", "three", "four"];
var i = arr.length; //initialize counter to array length
while (i--) //decrement counter
{
if (arr[i] === "four" || arr[i] === "two") {
console.log("Array after removal of ith element: ");
arr = arr.slice(0, i).concat(arr.slice(i + 1));
console.log(arr);
}
}
El método
Array.slice
es extremadamente importante para lograr la inmutabilidad en la programación funcional a la redux.
Auction.auction = Auction.auctions.filter(function(el) {
return --el["seconds"] > 0;
});
for (i = 0, len = Auction.auctions.length; i < len; i++) {
auction = Auction.auctions[i];
Auction.auctions[i][''seconds''] --;
if (auction.seconds < 0) {
Auction.auctions.splice(i, 1);
i--;
len--;
}
}