JavaScript busca y elimina objetos en una matriz según el valor clave


139

He estado intentando varios enfoques sobre cómo encontrar un objeto en una matriz, donde ID = var, y si se encuentra, elimine el objeto de la matriz y devuelva la nueva matriz de objetos.

Datos:

[
    {"id":"88","name":"Lets go testing"},
    {"id":"99","name":"Have fun boys and girls"},
    {"id":"108","name":"You are awesome!"}
]

Puedo buscar la matriz usando jQuery $ grep;

var id = 88;

var result = $.grep(data, function(e){ 
     return e.id == id; 
});

Pero, ¿cómo puedo eliminar todo el objeto cuando id == 88, y devolver datos como este:

Datos:

[
    {"id":"99","name":"Have fun boys and girls"},
    {"id":"108","name":"You are awesome!"}
]

¿Qué pasa con el uso de la slicefunción y un pequeño forbucle?
Ahmed Hamdy

1
Claro, pero, la razón por la que escribí esta pregunta, es porque estoy atascado;) ¿algún fragmento?
Tom


El título y el texto de la pregunta parecen estar en conflicto ... sugiriendo dos enfoques completamente diferentes: A. eliminar elementos de una matriz versus B. crear una nueva matriz filtrada.
canon

Respuestas:


155

Puedo grep la matriz para la identificación, pero ¿cómo puedo eliminar todo el objeto donde id == 88

Simplemente filtre por el predicado opuesto:

var data = $.grep(data, function(e){ 
     return e.id != id; 
});

12
Esta respuesta proporciona la solución más concisa e idiomática para jQuery
Bryan

1
En el caso en que desee eliminar todos los elementos con id = algo está bien ... pero tenga cuidado al usar $ .grep ya que busca en la matriz completa y para matrices largas no es eficiente. A veces solo necesita verificar si el elemento existe dentro de la matriz mediante una ID dada, entonces es mejor usar otro método de iteración;)
julianox

1
Esto no elimina ese objeto de la lista
Arun Sivan

1
@ArunSivan slicetampoco elimina nada. No estoy seguro de a qué te refieres. Si tiene un problema específico usted mismo, es posible que desee hacer una nueva pregunta .
Bergi

1
@Learnerdata.filter(e => !ids.includes(e.id))
Bergi

153

Aquí hay una solución si no está utilizando jquery:

myArray = myArray.filter(function( obj ) {
  return obj.id !== id;
});

2
¿Es esto mejor que hacerlo findIndex()y luego splice(index, 1)en la matriz principal?
Alex

empalme muta la matriz de origen. Con filtro tienes la opción.
velop

13
Puede reducir esto a una sola línea utilizando: myArr = myArray.filter (obj => obj.id! == id);
DBrown

2
aún más concisoarr = arr.filter( obj => obj.id !== id);
Omar

86

Puede simplificar esto, y realmente no hay necesidad de usar jquery aquí.

var id = 88;

for(var i = 0; i < data.length; i++) {
    if(data[i].id == id) {
        data.splice(i, 1);
        break;
    }
}

Simplemente recorra la lista, encuentre la identificación correspondiente, empalme y luego rompa para salir de su ciclo


17
+1, pero debe mencionar que esto elimina solo el primer elemento que coincida.
Bergi

66
... Y si necesita eliminar cada elemento coincidente, i=data.length; i > 0; i--realice un bucle en orden inverso con y no lo use break.
Jeremy Belolo

3
i = data.lengthromperá cualquiera data[i], debería ser algo asíi=data.length -1 ; i > -1; i--
distante

31

Hay un nuevo método para hacer esto en ES6 / 2015 utilizando findIndex y el operador de distribución de matriz:

const index = data.findIndex(obj => obj.id === id);
const newData = [
    ...data.slice(0, index),
    ...data.slice(index + 1)
]

Puede convertirlo en una función para su posterior reutilización como esta:

function remove(array, key, value) {
    const index = array.findIndex(obj => obj[key] === value);
    return index >= 0 ? [
        ...array.slice(0, index),
        ...array.slice(index + 1)
    ] : array;
}

De esta manera, puede eliminar elementos mediante diferentes claves utilizando un método (y si no hay ningún objeto que cumpla con los criterios, obtendrá la matriz original devuelta):

const newData = remove(data, "id", "88");
const newData2 = remove(data, "name", "You are awesome!");

O puede ponerlo en su Array.prototype:

Array.prototype.remove = function (key, value) {
    const index = this.findIndex(obj => obj[key] === value);
    return index >= 0 ? [
        ...this.slice(0, index),
        ...this.slice(index + 1)
    ] : this;
};

Y úsalo de esta manera:

const newData = data.remove("id", "88");
const newData2 = data.remove("name", "You are awesome!");

findIndex () es realmente genial! 👍
danielcraigie

9

Asumir que los identificadores son únicos y que solo tendrá que eliminar el elemento splicedebe hacer el truco:

var data = [
  {"id":"88","name":"Lets go testing"},
  {"id":"99","name":"Have fun boys and girls"},
  {"id":"108","name":"You are awesome!"}
],
id = 88;

console.table(data);

$.each(data, function(i, el){
  if (this.id == id){
    data.splice(i, 1);
  }
});

console.table(data);

Tiene los elementos en su función de devolución de llamada al revés. Debería ser each(data,function(idx,ele). Te facturaré más tarde por los 30 minutos que desperdicié resolviendo eso :)
CSharper

Ups Lo menos que puedo hacer en ese caso es actualizar mi respuesta. Me siento muy mal por tu pérdida de 30 minutos de vida.
James Hibbard el

5
var items = [
  {"id":"88","name":"Lets go testing"},
  {"id":"99","name":"Have fun boys and girls"},
  {"id":"108","name":"You are awesome!"}
];

Si está utilizando jQuery, use jQuery.grep así:

items = $.grep(items, function(item) { 
  return item.id !== '88';
});
// items => [{ id: "99" }, { id: "108" }]

Usando ES5 Array.prototype.filter :

items = items.filter(function(item) { 
  return item.id !== '88'; 
});
// items => [{ id: "99" }, { id: "108" }]

1
Noooooo! No use el jQuerymapa como filtro.
Bergi

1
¡De acuerdo! Su solución con grep es la solución correcta con jQuery.
nekman

4

Quizás estés buscando la $.grep()función:

arr = [
  {"id":"88","name":"Lets go testing"},
  {"id":"99","name":"Have fun boys and girls"},
  {"id":"108","name":"You are awesome!"}
];

id = 88;
arr = $.grep(arr, function(data, index) {
   return data.id != id
});

3

siftes un potente filtro de recopilación para operaciones como esta y otras mucho más avanzadas. Funciona del lado del cliente en el navegador o del lado del servidor en node.js.

var collection = [
    {"id":"88","name":"Lets go testing"},
    {"id":"99","name":"Have fun boys and girls"},
    {"id":"108","name":"You are awesome!"}
];
var sifted = sift({id: {$not: 88}}, collection);

Es compatible con filtros como $in, $nin, $exists, $gte, $gt, $lte, $lt, $eq, $ne, $mod, $all, $and, $or, $nor, $not, $size, $type, y $regex, y se esfuerza por ser con filtrado colección MongoDB compatibles API.


¿Por qué no hay upwotes? Si esta cosa está escrita correctamente y no tiene errores terribles, debería ser extremadamente útil.
Max Yari el

2
Array.prototype.removeAt = function(id) {
    for (var item in this) {
        if (this[item].id == id) {
            this.splice(item, 1);
            return true;
        }
    }
    return false;
}

Esto debería hacer el truco, jsfiddle


0

Asegúrese de forzar la identificación del objeto a un entero si prueba la igualdad estricta:

var result = $.grep(data, function(e, i) { 
  return +e.id !== id;
});

Manifestación


0

Si está utilizando subrayado js, ​​es fácil eliminar el objeto según la clave. http://underscorejs.org . Ejemplo:

  var temp1=[{id:1,name:"safeer"},  //temp array
             {id:2,name:"jon"},
             {id:3,name:"James"},
             {id:4,name:"deepak"},
             {id:5,name:"ajmal"}];

  var id = _.pluck(temp1,'id'); //get id array from temp1
  var ids=[2,5,10];             //ids to be removed
  var bool_ids=[];
  _.each(ids,function(val){
     bool_ids[val]=true;
  });
  _.filter(temp1,function(val){
     return !bool_ids[val.id];
  });
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.