Compruebe si el valor del objeto existe dentro de una matriz de objetos Javascript y, si no, agregue un nuevo objeto a la matriz

146

Si tengo la siguiente matriz de objetos:

[ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ]

¿Hay alguna manera de recorrer la matriz para verificar si ya existe un valor de nombre de usuario en particular y si no hace nada, pero si no lo hace, agregar un nuevo objeto a la matriz con dicho nombre de usuario (y nueva ID)?

¡Gracias!

usuario2576960
fuente
1
¿Se supone que Bill y Ted tienen la misma identificación?
user2357112 es compatible con Monica el
¿Por qué hay dos elementos con lo mismo id? ¿Es posible que los elementos se eliminen de esta matriz, o podemos estar seguros de que el nuevo elemento siempre tendrá el idmismo valor arr.length + 1?
raina77ow
Si no desea recorrerlo, consulte estas preguntas y respuestas para ampliar el prototipo de matriz, stackoverflow.com/questions/1988349/… .
Cem Özer
las funciones nativas son más lentas en comparación con los bucles normales y su soporte está limitado a algunas versiones del navegador. mira mi respuesta a continuación.
Zaheen
Esta es una pregunta fundamentalmente incorrecta porque puede hacerlo evitando el uso de matrices.
Bekim Bacaj

Respuestas:

234

Supuse que los ids están destinados a ser únicos aquí. somees una gran función para verificar la existencia de cosas en matrices:

const arr = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];

function add(arr, name) {
  const { length } = arr;
  const id = length + 1;
  const found = arr.some(el => el.username === name);
  if (!found) arr.push({ id, username: name });
  return arr;
}

console.log(add(arr, 'ted'));

Andy
fuente
1
Gracias Andy, esta es una solución muy limpia al problema y está funcionando muy bien. No había encontrado algún método antes. Su suposición era correcta, mi ejemplo de ID era solo un error tipográfico, estaba usando arr.length + 1 para determinar la ID.
user2576960
3
Tenga en cuenta que IE8 y versiones anteriores no son compatibles con alguna función.
BetaRide
¿Se puede convertir la función encontrada en un IF? Algo como: if (arr.some (function (el) {el.Id == someId) y devolverá verdadero o falso si existe o no?
stibay

@stibay, some hace regresar un valor lógico. foundserá trueo falsedependiendo de si se cumple la condición en la devolución de llamada.
Andy

1
Oh, claro: if (arr.some(function (el) { return el.Id == someId; })) { // do something }. No lo olvides returno no recuperarás nada.
Andy

26

Es bastante trivial verificar el nombre de usuario existente:

var arr = [{ id: 1, username: 'fred' }, 
  { id: 2, username: 'bill'}, 
  { id: 3, username: 'ted' }];

function userExists(username) {
  return arr.some(function(el) {
    return el.username === username;
  }); 
}

console.log(userExists('fred')); // true
console.log(userExists('bred')); // false

Pero no es tan obvio qué hacer cuando tiene que agregar un nuevo usuario a esta matriz. La salida más fácil: simplemente empujando un nuevo elemento con idigual a array.length + 1:

function addUser(username) {
  if (userExists(username)) {
    return false; 
  }
  arr.push({ id: arr.length + 1, username: username });
  return true;
}

addUser('fred'); // false
addUser('bred'); // true, user `bred` added

Garantizará la unicidad de los ID, pero hará que esta matriz se vea un poco extraña si se quitan algunos elementos.


Gracias por esto. Fui con la solución de Andy al final porque es una forma más sucinta de lograr lo mismo. No eliminaré usuarios en ningún momento, por lo que las ID deben permanecer consistentes. La verificación permite a los usuarios iniciar sesión, cerrar sesión y volver a iniciarla sin que la matriz crezca horas extras. Solo para obtener información, estoy usando esta función junto con passport.js y no he podido encontrar una forma de eliminar usuarios de la matriz sin jugar con el código del pasaporte en sí. Esta solución funciona muy bien.
user2576960


10

Creo que esta es la forma más corta de abordar este problema. Aquí he usado la función de flecha ES6 con .filter para verificar la existencia de un nuevo nombre de usuario agregado.

var arr = [{
    id: 1,
    username: 'fred'
}, {
    id: 2,
    username: 'bill'
}, {
    id: 3,
    username: 'ted'
}];

function add(name) {
    var id = arr.length + 1;        
            if (arr.filter(item=> item.username == name).length == 0){
            arr.push({ id: id, username: name });
        }
}

add('ted');
console.log(arr);

Enlace a violín


3

Esto es lo que hice además de la respuesta de @ sagar-gavhane

const newUser = {_id: 4, name: 'Adam'}
const users = [{_id: 1, name: 'Fred'}, {_id: 2, name: 'Ted'}, {_id: 3, 'Bill'}]

const userExists = users.some(user => user.name = newUser.name);
if(userExists) {
    return new Error({error:'User exists'})
}
users.push(newUser)

Hola, si encontré el valor, ¿cómo puedo acceder a la identificación?
Kusal Kithmal

Es realmente simple hacer eso... if(userExists) { const userId = userExists.id return userId; } ...
Michael Enitan, el

2

La respuesta aceptada también se puede escribir de la siguiente manera usando la función de flecha en .some

 function checkAndAdd(name) {
     var id = arr.length + 1;
     var found = arr.some((el) => {
           return el.username === name;
     });
     if (!found) { arr.push({ id: id, username: name }); }
 }

1

Me gusta la respuesta de Andy, pero la identificación no necesariamente será única, así que esto es lo que se me ocurrió para crear una identificación única también. También se puede verificar en jsfiddle . Tenga en cuenta que es arr.length + 1muy posible que no garantice una identificación única si se ha eliminado algo anteriormente.

var array = [ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' } ];
var usedname = 'bill';
var newname = 'sam';

// don't add used name
console.log('before usedname: ' + JSON.stringify(array));
tryAdd(usedname, array);
console.log('before newname: ' + JSON.stringify(array));
tryAdd(newname, array);
console.log('after newname: ' + JSON.stringify(array));

function tryAdd(name, array) {
    var found = false;
    var i = 0;
    var maxId = 1;
    for (i in array) {
        // Check max id
        if (maxId <= array[i].id)
            maxId = array[i].id + 1;

        // Don't need to add if we find it
        if (array[i].username === name)
            found = true;
    }

    if (!found)
        array[++i] = { id: maxId, username: name };
}

Me gusta la simplicidad en las otras respuestas, acabo de publicar la mía para agregar el cheque de identificación única
Uxonith

Gracias por tu respuesta Uxonith. Por el momento no necesito una identificación única porque no eliminaré usuarios de la matriz. Mantendré esta resolución en mi bolsillo trasero en caso de que surja la necesidad. Gracias de nuevo
user2576960

1

Podrías crear un prototipo de tu matriz para hacerla más modular, prueba algo como esto

    Array.prototype.hasElement = function(element) {
        var i;
        for (i = 0; i < this.length; i++) {
            if (this[i] === element) {
                return i; //Returns element position, so it exists
            }
        }

        return -1; //The element isn't in your array
    };

Y puedes usarlo como:

 yourArray.hasElement(yourArrayElement)

1

Intenté los pasos anteriores por alguna razón, parece que no funciona para mí, pero esta fue mi solución final a mi propio problema, tal vez útil para cualquiera que lea esto:

let pst = post.likes.some( (like) => {  //console.log(like.user, req.user.id);
                                     if(like.user.toString() === req.user.id.toString()){
                                         return true
                                     } } )

aquí post.likes es una variedad de usuarios a los que les gustó una publicación.


1

prueba esto

primer método usando algunos

  let arr = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];
    let found = arr.some(ele => ele.username === 'bill');
    console.log(found)

segundo método usando incluye, mapa

   let arr = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];
    let mapped = arr.map(ele => ele.username);
    let found = mapped.includes('bill');
    console.log(found)

¿Qué sucede si quiero comparar objetos con 2 atributos como {"nombre": "prueba1", "edad": 30}?
probitaille
1

Supongamos que tenemos una matriz de objetos y desea verificar si el valor del nombre se define así,

let persons = [ {"name" : "test1"},{"name": "test2"}];

if(persons.some(person => person.name == 'test1')) {
    ... here your code in case person.name is defined and available
}
Hasan Zahran
fuente
Agregue algunas oraciones para explicar lo que está haciendo su código, para que pueda obtener más votos a favor para su respuesta.
Análisis difuso el
¿Qué sucede si quiero comparar objetos con 2 atributos como {"nombre": "prueba1", "edad": 30}?
probitaille
1

Aquí hay una cadena de métodos ES6 que usa .map()y .includes():

const arr = [ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ]

const checkForUser = (newUsername) => {
      arr.map(user => {
        return user.username
      }).includes(newUsername)
    }

if (!checkForUser('fred')){
  // add fred
}
  1. Asigne sobre usuarios existentes para crear una matriz de cadenas de nombre de usuario.
  2. Compruebe si ese conjunto de nombres de usuario incluye el nuevo nombre de usuario
  3. Si no está presente, agregue el nuevo usuario
Len Joseph
fuente
0

Las funciones nativas de la matriz a veces son entre 3 y 5 veces más lentas que los bucles normales. Además, las funciones nativas no funcionarán en todos los navegadores, por lo que hay problemas de compatibilidad.

Mi código:

<script>
  var obj = [];

  function checkName(name) {
    // declarations
    var flag = 0;
    var len = obj.length;   
    var i = 0;
    var id = 1;

    // looping array
    for (i; i < len; i++) {
        // if name matches
        if (name == obj[i]['username']) {
            flag = 1;
            break;
        } else {
            // increment the id by 1
            id = id + 1;
        }
    }

    // if flag = 1 then name exits else push in array
    if (flag == 0) {
      // new entry push in array        
      obj.push({'id':id, 'username': name});
    }
  }
  // function end

  checkName('abc');
</script>

De esta manera puede lograr resultados más rápido.

Nota: No he verificado si el parámetro pasado está vacío o no, si lo desea, puede marcarlo o escribir una expresión regular para una validación particular.

Zaheen
fuente
0

xorWith en Lodash se puede usar para lograr esto

let objects = [ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ]
let existingObject = { id: 1, username: 'fred' };
let newObject = { id: 1729, username: 'Ramanujan' }

_.xorWith(objects, [existingObject], _.isEqual)
// returns [ { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ]

_.xorWith(objects, [newObject], _.isEqual)
// returns [ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ,{ id: 1729, username: 'Ramanujan' } ]
sudo bangbang
fuente
0

function number_present_or_not () { var arr = [ 2,5,9,67,78,8,454,4,6,79,64,688 ] ; var encontrado = 6; var encontrado_dos; para (i = 0; i

    }
    if ( found_two == found )
    {
        console.log("number present in the array");
    }
    else
    {
        console.log("number not present in the array");
    }
}
Nakkeeran 8797
fuente
-1

La mejor práctica es así.

var arr = ["a","b","c","d"];
console.log(arr.includes("a")); //---- true;
console.log(arr.includes("k")); //---- false;
console.log(arr.includes("c")); //---- true;
Lluvia azul
fuente
18
La pregunta es sobre la matriz de objetos y esto no funcionará.
Adrián Enríquez
Esta no es la respuesta correcta para la pregunta.
Ahsan Mukhtar
Esta respuesta no es suficiente con el requisito mencionado en la pregunta.
Savan Gadhiya