Verifique se o valor do objeto existe em uma matriz de objetos Javascript e se não adicionar um novo objeto à matriz

146

Se eu tiver a seguinte matriz de objetos:

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

Existe uma maneira de percorrer a matriz para verificar se já existe um valor de nome de usuário específico e se não faz nada, mas se não adicionar um novo objeto à matriz com o nome de usuário (e o novo ID)?

Obrigado!

user2576960
fonte
1
Bill e Ted deveriam ter o mesmo ID?
User2357112 suporta Monica
Por que existem dois elementos com o mesmo id? É possível que os elementos sejam removidos dessa matriz ou podemos ter certeza de que o novo elemento sempre será idigual a arr.length + 1?
raina77ow
Se você não quiser fazer um loop, verifique estas perguntas e respostas para estender o protótipo de array, stackoverflow.com/questions/1988349/… .
Cem Özer 03/04
as funções nativas são mais lentas em comparação com os loops normais e seu suporte é limitado a algumas versões do navegador. verifique minha resposta abaixo.
Zaheen
essa é uma pergunta fundamentalmente errada, porque você pode fazer isso evitando o uso de matrizes.
Bekim Bacaj

Respostas:

234

Eu assumi que ids devem ser únicos aqui. someé uma ótima função para verificar a existência de coisas nas matrizes:

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
fonte
1
Obrigado Andy, esta é uma solução muito limpa para o problema e está funcionando muito bem. Eu nunca tinha encontrado algum método antes. Sua suposição estava correta, meu exemplo de ID foi apenas um erro de digitação, eu estava usando arr.length + 1 para determinar a ID.
precisa saber é o seguinte
3
Cuidado que o IE8 e versões anteriores não suportam a função some.
BetaRide 13/10
A função encontrada pode ser transformada em um IF? Algo como: if (arr.some (function (el) {el.Id == someId) e ele irá retornar verdadeiro ou falso, se ele existe ou não?
stibay

@stibay, some faz retornar um boolean. foundserá trueou falsedependendo se a condição no retorno de chamada é atendida.
Andy Andy

1
Ah, claro: if (arr.some(function (el) { return el.Id == someId; })) { // do something }. Não esqueça disso returnou você não receberá nada de volta.
Andy

26

É bastante trivial verificar o nome de usuário 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

Mas não é tão óbvio o que fazer quando você precisa adicionar um novo usuário a essa matriz. A saída mais fácil - basta pressionar um novo elemento com 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

Isso garantirá a exclusividade dos IDs, mas fará com que essa matriz pareça um pouco estranha se alguns elementos forem retirados do final.


Obrigado por isso. Eu fui com a solução de Andy no final, porque é uma maneira mais sucinta de conseguir a mesma coisa. Não removerei usuários a qualquer momento, portanto os IDs devem permanecer consistentes. A verificação permite que os usuários efetuem login, logoff e logon novamente sem que a matriz cresça horas extras. Apenas para informações, estou usando esta função em conjunto com o passport.js e não consegui encontrar uma maneira de remover usuários da matriz sem jogar com o próprio código do passaporte. Esta solução funciona bem.
user2576960


10

Eu acho que, essa é a maneira mais curta de resolver esse problema. Aqui, usei a função de seta ES6 com .filter para verificar a existência da adição de um novo nome de usuário.

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


3

Foi o que fiz além da resposta 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)

Oi, Se eu encontrei o valor, como posso acessar o ID?
Kusal Kithmal

É realmente simples fazer isso #... if(userExists) { const userId = userExists.id return userId; } ...
Michael Enitan 31/12/19

2

A resposta aceita também pode ser escrita da seguinte maneira, usando a função de seta em .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

Gosto da resposta de Andy, mas o ID não será necessariamente único, então aqui está o que eu criei para criar um ID exclusivo também. Também pode ser verificado no jsfiddle . Observe que arr.length + 1pode muito bem não garantir um ID exclusivo se algo tiver sido removido 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 };
}

Eu gosto da simplicidade nas outras respostas, eu só postou mina para adicionar a verificação de identificação única
Uxonith

Obrigado pela sua resposta Uxonith. No momento, não preciso de um ID exclusivo, porque não removerei os usuários da matriz. Manterei esta resolução no bolso de trás, caso seja necessário. Obrigado novamente
user2576960

1

Você pode criar um protótipo do seu array para torná-lo mais modular, tente algo como isto

    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 você pode usá-lo como:

 yourArray.hasElement(yourArrayElement)

1

Eu tentei as etapas acima por algum motivo, parece que não está funcionando para mim, mas esta foi a minha solução final para o meu próprio problema, talvez útil para quem estiver lendo isso:

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

aqui post.likes é uma matriz de usuários que curtiram uma postagem.


1

tente isso

primeiro método usando alguns

  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 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 eu quiser comparar objetos com 2 atributos, como {"name": "test1", "age": 30}?
probitaille 17/07
1

Vamos supor que temos uma matriz de objetos e você deseja verificar se o valor do nome está definido assim,

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
fonte
Adicione algumas frases para explicar o que seu código está fazendo, para que você possa obter mais votos positivos para sua resposta.
Fuzzy Analysis
E se eu quiser comparar objetos com 2 atributos, como {"name": "test1", "age": 30}?
probitaille 17/07
1

Aqui está uma cadeia de métodos ES6 usando .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. Mapeie os usuários existentes para criar uma matriz de cadeias de nomes de usuários.
  2. Verifique se essa matriz de nomes de usuário inclui o novo nome de usuário
  3. Se não estiver presente, adicione o novo usuário
Len Joseph
fonte
0

Às vezes, as funções nativas do array são 3 a 5 vezes mais lentas que os loops normais. Além disso, as funções nativas não funcionam em todos os navegadores, por isso há problemas de compatibilidade.

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

Dessa forma, você pode obter resultados mais rapidamente.

Nota: Eu não verifiquei se o parâmetro passado está vazio ou não; se você quiser, pode verificar ou escrever uma expressão regular para validação específica.

Zaheen
fonte
0

xorWith no Lodash pode ser usado para conseguir isso

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

função number_present_or_not () { var arr = [ 2,5,9,67,78,8,454,4,6,79,64,688 ] ; var encontrada = 6; var found_two; 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
fonte
-1

A melhor prática é assim.

var arr = ["a","b","c","d"];
console.log(arr.includes("a")); //---- true;
console.log(arr.includes("k")); //---- false;
console.log(arr.includes("c")); //---- true;
Chuva azul
fonte
18
A questão é sobre a matriz de objetos e isso não vai funcionar.
Adrian Enriquez
Esta não é a resposta certa para a pergunta.
Ahsan Mukhtar
esta resposta não é suficiente para o requisito mencionado na pergunta.
Savan Gadhiya