Controllare se esiste un valore oggetto all'interno di un array Javascript di oggetti e se non aggiungere un nuovo oggetto all'array


147

Se ho il seguente array di oggetti:

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

C'è un modo per passare in rassegna l'array per verificare se esiste già un determinato valore del nome utente e se non fa nulla, ma se non aggiunge un nuovo oggetto all'array con detto nome utente (e nuovo ID)?

Grazie!


1
Bill e Ted dovrebbero avere lo stesso ID?
user2357112 supporta Monica

Perché ci sono due elementi con lo stesso id? È possibile che gli elementi vengano rimossi da questo array o possiamo essere sicuri che il nuovo elemento avrà sempre iduguale arr.length + 1?
raina77ow,

Se non si desidera eseguire il ciclo, consultare le Domande e risposte per estendere il prototipo dell'array, stackoverflow.com/questions/1988349/… .
Cem Özer,

le funzioni native sono più lente rispetto ai normali loop e il loro supporto è limitato ad alcune versioni del browser. controlla la mia risposta qui sotto.
Zaheen,

questa è una domanda fondamentalmente sbagliata perché puoi farlo evitando l'uso di array.
Bekim Bacaj,

Risposte:


235

Ho supposto che ids siano fatti per essere unici qui. someè un'ottima funzione per verificare l'esistenza di cose negli array:

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


1
Grazie Andy, questa è una soluzione molto chiara al problema e funziona molto bene. Non avevo mai incontrato il metodo prima. La tua ipotesi era corretta il mio esempio ID era solo un errore di battitura, stavo usando arr.length + 1 per determinare l'ID.
user2576960

3
Attenzione, IE8 e precedenti non supportano la funzione some.
BetaRide,

La funzione trovata può essere trasformata in un IF? Qualcosa del tipo: if (arr.some (function (el) {el.Id == someId) e restituirà vero o falso se esiste o no?
stibay

@stibay, some fa ritornare un valore booleano. foundsarà trueo a falseseconda che sia soddisfatta la condizione nel callback.
Andy,

1
Oh, certo: if (arr.some(function (el) { return el.Id == someId; })) { // do something }. Non dimenticarlo returno non otterrai nulla in cambio.
Andy,

26

È piuttosto banale controllare il nome utente esistente:

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

Ma non è così ovvio cosa fare quando si deve aggiungere un nuovo utente a questo array. La via d'uscita più semplice: basta spingere un nuovo elemento iduguale 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

Garantirà l'unicità degli ID, ma renderà un po 'strano questo array se alcuni elementi verranno rimossi dalla sua estremità.


Grazie per questo. Alla fine sono andato con la soluzione di Andy perché è un modo più conciso di ottenere la stessa cosa. Non rimuoverò gli utenti in nessun momento, quindi gli ID dovrebbero rimanere coerenti. Il controllo consente agli utenti di accedere, uscire e riconnettersi senza che l'array aumenti gli straordinari. Solo per informazioni sto usando questa funzione insieme a passport.js e non sono stato in grado di trovare un modo per rimuovere gli utenti dall'array senza giocare con il codice passaporto stesso. Questa soluzione funziona bene.
user2576960


10

Penso che questo sia il modo più breve per affrontare questo problema. Qui ho usato la funzione freccia ES6 con .filter per verificare l'esistenza di un nuovo nome utente.

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

Link a Fiddle


3

Questo è ciò che ho fatto oltre alla risposta di @ 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)

Ciao, se trovassi il valore come posso accedere all'ID?
Kusal Kithmal,

È davvero semplice farlo... if(userExists) { const userId = userExists.id return userId; } ...
Michael Enitan il

2

La risposta accettata può anche essere scritta nel modo seguente usando la funzione freccia su .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 }); }
 }

2

Ecco una catena di metodi ES6 che utilizza .map()e .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. Mappare gli utenti esistenti per creare una serie di stringhe di nomi utente.
  2. Controlla se quell'array di nomi utente include il nuovo nome utente
  3. Se non è presente, aggiungi il nuovo utente

1

Mi piace la risposta di Andy, ma l'id non sarà necessariamente unico, quindi ecco cosa mi è venuto in mente per creare anche un ID univoco. Può essere controllato anche su jsfiddle . Si noti che arr.length + 1potrebbe non garantire un ID univoco se qualcosa è stato rimosso in precedenza.

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

Mi piace la semplicità nelle altre risposte, ho appena pubblicato il mio per aggiungere il controllo per ID univoco
Uxonith

Grazie per la tua risposta Uxonith. Al momento non ho bisogno di un ID univoco perché non rimuoverò gli utenti dall'array. Terrò questa risoluzione nella mia tasca posteriore in caso di necessità. Grazie ancora
user2576960

1

Potresti prototipare il tuo array per renderlo più modulare, provare qualcosa del genere

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

E puoi usarlo come:

 yourArray.hasElement(yourArrayElement)

1

ho provato i passaggi precedenti per qualche motivo che sembra non funzionare per me, ma questa è stata la mia soluzione finale al mio problema, forse utile a chiunque legga questo:

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

qui post.likes è un array di utenti a cui è piaciuto un post.


1

prova questo

primo metodo usando alcuni

  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)

secondo metodo usando include, map

   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)

E se volessi confrontare oggetti con 2 attributi come {"name": "test1", "age": 30}?
Probitaille,

1

Supponiamo di avere una matrice di oggetti e vuoi verificare se il valore del nome è definito in questo modo,

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

if(persons.some(person => person.name == 'test1')) {
    ... here your code in case person.name is defined and available
}

Aggiungi alcune frasi per spiegare cosa sta facendo il tuo codice, in modo da poter ottenere più voti per la tua risposta.
Analisi fuzzy

E se volessi confrontare oggetti con 2 attributi come {"name": "test1", "age": 30}?
Probitaille,

0

Le funzioni native dell'array sono talvolta 3X - 5X volte più lente dei normali loop. Inoltre le funzioni native non funzioneranno in tutti i browser, quindi sussistono problemi di compatibilità.

Il mio codice:

<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>

In questo modo è possibile ottenere risultati più velocemente.

Nota: non ho verificato se il parametro passato è vuoto o meno, se vuoi puoi metterlo su un controllo o scrivere un'espressione regolare per una convalida particolare.


0

xorWith a Lodash può essere usato per raggiungere questo obiettivo

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


0

funzione number_present_or_not () { var arr = [ 2,5,9,67,78,8,454,4,6,79,64,688 ] ; var found = 6; var found_two; per (i = 0; i

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

-1

La migliore pratica è così.

var arr = ["a","b","c","d"];
console.log(arr.includes("a")); //---- true;
console.log(arr.includes("k")); //---- false;
console.log(arr.includes("c")); //---- true;

18
La domanda riguarda l'array di oggetti e questo non funzionerà.
Adrian Enriquez,

questa non è la risposta giusta per la domanda.
Ahsan Mukhtar,

questa risposta non è sufficiente ai requisiti indicati nella domanda.
Savan Gadhiya il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.